2016-01-10 18 views
10

मैं आरएक्स के लिए नया ब्रांड हूं और मुझे वादे लिखने पर दस्तावेज ढूंढना मुश्किल लगता है जैसे कि पहले वादे से डेटा दूसरे में पारित किया जाता है। यहां तीन बहुत ही बुनियादी वादे हैं, डेटा पर गणना महत्वपूर्ण नहीं है, बस पिछले वादे से डेटा का उपयोग करके कुछ एसिंक को किया जाना चाहिए।आरएक्सजेएस वादा संरचना (डेटा उत्तीर्ण)

const p1 =() => Promise.resolve(1); 
const p2 = x => { const val = x + 1; return Promise.resolve(val); }; 
const p3 = x => { 
     const isEven = x => x % 2 === 0; 
     return Promise.resolve(isEven(x)); 
}; 

रचना के बारे में मैं बात कर रहा हूँ प्राप्त करने के लिए परंपरागत तरीके:

R.pipeP(p1, p2, p3, console.log)() 

ऐसा लगता है की संभावना आरएक्स सक्षम हो सकता है:

pl().then(p2).then(p3).then(console.log); 

मेरा पसंदीदा कार्यान्वयन Ramda के composeP और pipeP है इस तरह की स्थिति को बहुत आसानी से संभालने के लिए।

var Rx = require('rx'), 
    fs = require('fs'), 
    path = require('path'); 
var file = path.join(__dirname, 'file.txt'), 
    dest = path.join(__dirname, 'file1.txt'), 
    exists = Rx.Observable.fromCallback(fs.exists), 
    rename = Rx.Observable.fromNodeCallback(fs.rename), 
    stat = Rx.Observable.fromNodeCallback(fs.stat); 
exists(file) 
    .concatMap(function (flag) { 
    return flag ? 
     rename(file, dest) : 
     Rx.Observable.throw(new Error('File does not exist.')); 
    }) 
    .concatMap(function() { 
     return stat(dest); 
    }) 
    .forEach(
     function (fsStat) { 
      console.log(JSON.stringify(fsStat)); 
     }, 
     function (err) { 
      console.log(err); 
     } 
    ); 

concatMap होनहार लगता है, लेकिन इसके बाद के संस्करण कोड सुंदर भीषण दिखता है: हालांकि, सबसे करीब मैं अब तक मिल गया है (पुस्तकालय) यहाँ https://github.com/Reactive-Extensions/RxJS/blob/master/doc/mapping/async/comparing.md तुलना async को RxJS से है। मुझे अपने उदाहरण में भी परेशानी हो रही थी क्योंकि Rx.Observable.fromromromise (p1) काम नहीं करेगा क्योंकि यह एक वादा की अपेक्षा करता है, एक समारोह नहीं, और Rx.Observable.defer (p1) पैरामीटर को पारित नहीं करता है उदाहरण।

धन्यवाद!

इसी प्रकार के प्रश्न लेकिन डेटा गुजर बिना: Chaining promises with RxJS

+0

क्या आपके वादों को किसी फ़ंक्शन में लपेटना है? – user3743222

+0

केवल उसमें यदि आपने वादा श्रृंखला के बाहर एक वादा इनलाइन परिभाषित की है या कुछ ऐसा है जो कॉन्स पी 1 = नया वादा ((संकल्प, अस्वीकार) => {}) के साथ देखा जा सकता है, तो यह तुरंत मूल्यांकन करना शुरू कर देगा और पहले से डेटा प्राप्त नहीं कर सका निष्पादित वादा या क्या मैं तत्काल मूल्यांकन के बारे में गलत हूं? –

उत्तर

14

मैं जा रहा है समारोह लौटने का वादा किया p के साथ यह सब पढ़ नहीं था, लेकिन अगर आप pl().then(p2).then(p3).then(console.log); के रूप में ही हासिल करना चाहते हैं, आप (उदाहरण की तरह कुछ कर सकता है here)

Rx.Observable.fromPromise(p1()) 
      .flatMap(function(p1_result){return p2(p1_result);}) 
      .flatMap(function(p2_result){return p3(p2_result);}) 

या अधिक सममित:

var chainedPromises$ = 
    Rx.Observable.just() 
      .flatMap(p1) 
      .flatMap(p2) 
      .flatMap(p3); 

अब अगर आप क्रमिक रूप से कॉलबैक fromCallback या fromNodeCallback के माध्यम से लिपटे निष्पादित करने के लिए चाहते हैं, आप की तरह कुछ कर सकता है:

function rename (flag){ 
    return flag 
      ? rename(file,dest).flatMap(return Rx.Observable.just(dest)) 
      : Rx.Observable.throw(new Error('File does not exist.')); 
} 

Rx.Observable.just(file) 
      .flatMap(exists) 
      .flatMap(rename) 
      .flatMap(stat) 

उत्तरार्द्ध कोड अपरीक्षित है, इसलिए मुझे लगता है कि अगर काम करता है को अपडेट रखने के। अंतिम टिप्पणी, यह काम करना चाहिए यदि प्रत्येक बिंदु पर आपके पास केवल एक मूल्य उत्पन्न होता है (एक वादा की तरह)। यदि आपके पास flatMap के साथ एक की बजाय कई फाइलें होंगी, तो आपको ऑर्डरिंग ऑर्डर मिल सकते हैं (यदि ऑर्डर आपके लिए मायने रखता है), तो उस स्थिति में, आप प्रतिस्थापन के रूप में concatMap का उपयोग कर सकते हैं।

+0

मैं कुछ हद तक थोड़ा अधिक अमूर्तता की उम्मीद कर रहा था जो flatMapAll (p1, p2, p3) जैसा कुछ होगा। विशेष रूप से सहायक यदि नक्शे के माध्यम से वादे का अनुक्रम उत्पन्न होता है उदा। कॉन्स पीएस = मैप ((एक्स) => वादा किया गया है रीडफाइल कूरिडसैटैट इट डोज़थिंग विथ प्राइफाइलफाइलडाटा (एक्स), ['1.txt', '2.txt', '3.txt']); । Rx.Observable.just() flatMapAll (... ps); (बस छद्म कोड)। लेकिन यह निश्चित रूप से एक प्रबंधनीय समाधान है और संभावित रूप से समझौता या कुछ से मैपिंग के साथ ऐसा करने का एक तरीका है। धन्यवाद! –

+0

ने दूसरे कोड नमूने का भी परीक्षण नहीं किया, लेकिन पहले लोग आकर्षण –

+0

की तरह काम करते हैं, आप स्वयं 'flatMapAll' कर सकते हैं। 'flatMapAll :: Rx.Observable -> [a -> a] -> Rx.Observable'। 'flatMapAll = (स्रोत, fn_array) -> fn_array.reduce ((एसीसी, एफएन) -> acc.flatMap (एफएन), स्रोत)'। जेएस में, 'Rx.Observable.prototype.flatMapAll = फ़ंक्शन (fn_array) {source = this; वापसी ...} ' – user3743222

संबंधित मुद्दे