2016-11-06 23 views
5

私はネストされた観測可能な地獄で立ち往生しており、手で行うことができます。ネストしたObservablesを平坦化する

Iは、次のコードブロック

return this.findUser(term).map(users => { 
    return users.map(user => this.getLastLogin(user.user_id).map(last_login => { 
    user.last_login = last_login; 
    return user; 
    })); 
}); 

findUser戻りObservable<User[]>getLastLogin戻りObservable<number>を有します。

私は基本的にユーザーのリストを取得し、別の値の情報でこれを更新することを望んでいます。

今すぐ上のコードは<Observable<Observable<User>[]>を返しています。

mapflatMapに置き換えることができると考えましたが、これはオブジェクトを<Observable<Observable<User>>に変えます。

RxJSのドキュメントは少し解読しにくいので、switchforkJoinまたはflatMapの組み合わせが私に必要なものを手に入れてくれるかどうかはわかりません。

私はObservable<User[]>を返すことを望んでいます。誰かが私を正しい方向に向けることができますか?

答えて

4

実は、あなたはこれを行うにはforkJoin()switch()を必要としません。

通常、別の非同期呼び出しによってユーザーのアレイ内の各ユーザーを更新する必要があります。

私はこのようにそれを行うだろう:

var source = findUser('term') 
    .mergeAll() 
    .mergeMap(user => getLastLogin(user.user_id) 
     .map(last_login => { 
      user.last_login = last_login; 
      return user; 
     }) 
    ) 
    .toArray(); 

source.subscribe(val => console.log(val)); 

オペレータmergeAll()単一の観測に観察可能な高次に変換します。この場合、すべてのユーザーの配列を取り、1つずつ再発行します。その後、mergeMap()last_loginの日付で更新されたユーザーを放出します。最後に私はtoArray()を使用して、単一のユーザーを1つの大きな配列に変換しました。この配列は全体として放出されます(単一のユーザーを放出する場合はこの演算子を削除できます)。あなたがreturn users.map(...)を使用したとき、あなたが観察を返しアレイとないmap() RxJSからを返すArray.map()を使用していたことを

は注意してください。私は単一のオブジェクトで作業するのは、通常、オブジェクトの配列で簡単だと思います。

はライブデモを参照してください:https://jsbin.com/naqudun/edit?js,console

はこれがコンソールに出力します。

[ { name: 'foo', 
    user_id: 42, 
    last_login: 2016-11-06T10:28:29.314Z }, 
    { name: 'bar', 
    user_id: 21, 
    last_login: 2016-11-06T10:28:29.316Z } ] 
+0

私はあなたが滑らかな印象の答えだと思う - 質問のタイトルは、ネストされた観測を平坦に言及し、特にとして - しかし、私はか否かの好奇心配列の順序は常にソース配列の配列と一致します: 'mergeMap'を使用すると非決定論的な順序になりますか?順序は、どの観測対象が最初に放出されるかによって異なりますか? – cartant

+1

これは真であり、 'merge'も' mergeAll'も問題の可能性のある順序と同じ順序を保証します。しかし、問題であれば、 'mergeMap'を' concatMap'で置き換えることができます。それだけです。 – martin

+1

興味深いことに、このコードはTypeScriptのクラスを使用するときには機能しません。コンパイルすると、 'findUsers'メソッドの' mergeAll'が 'User []'を返すように見えます。ここに私が見ている行動へのリンクがあります。 https://jsbin.com/wiwayikiye/edit?js,console任意のアイデアですか? – user3750194

1

一つの解決策は、参加して、ユーザーにgetLastLoginへの呼び出しの結果をマッピングするためにforkJoinを使用することです:

// forkJoin will return Observable<User[]>, so use switchMap. 

return this.findUser(term).switchMap(users => Observable.forkJoin(

    // Map the array of users to the array of observables to be joined. Use 
    // first to ensure the observables complete. 

    users.map(user => this.getLastLogin(user.user_id).first()), 

    // Use forkJoin's selector to add the last_login to each user and return 
    // the users. 

    (...logins) => { 
    users.forEach((user, index) => { user.last_login = logins[index]; }); 
    return users; 
    } 
)); 
関連する問題