web-dev-qa-db-ja.com

RxJS Promise Composition(データを渡す)

私はRxを初めて使用し、最初のプロミスのデータが2番目のプロミスに渡されるように、プロミスの作成に関するドキュメントを見つけるのが難しいと感じています。 3つの非常に基本的な約束があります。データの計算は重要ではなく、前の約束からのデータを使用して非同期を行う必要があるだけです。

 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));
 };

私が話している構図を達成するための伝統的な方法:

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

私のお気に入りの実装は、ラムダのcomposePとpipePです。

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

Rxはこの種の状況をかなり流fluentに処理できる可能性があるようです。ただし、これまでのところ、RxJSと非同期(ライブラリ)の比較はここで最も近いものです https://github.com/Reactive-Extensions/RxJS/blob/master/doc/mapping/async/comparing .md

 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は有望に思えますが、上記のコードは非常に恐ろしく見えます。 Rx.Observable.fromPromise(p1)は関数ではなくプロミス自体を期待しているため動作せず、Rx.Observable.defer(p1)は次のようなパラメーターを渡さないため例。

ありがとう!

同様の質問ですが、データの受け渡しはありません: RxJSでの約束のチェーン化

16
low_ghost

すべてを読みませんでしたが、pがプロミスを返す関数であるpl().then(p2).then(p3).then(console.log);と同じことを達成したい場合、次のようなことができます(例 ここ

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)

後者のコードはテストされていないため、機能する場合は更新してください。最後のコメント、これは各ポイントで1つの値しか生成されない場合に機能するはずです(約束など)。 1つではなく複数のファイルがあり、flatMapを使用すると、順序の問題が発生する可能性があります(順序が重要な場合)。その場合、代わりにconcatMapを使用できます。

23
user3743222