2017-04-25 16 views
1

私は2つのオブジェクトのストリーム、勘定と残高を持っています。特定の条件に従ってRxJsのオブザーバブルストリームを2つ結合する

私が期待されている何idaccount_id

var accounts = Rx.Observable.from([ 
    { id: 1, name: 'account 1' }, 
    { id: 2, name: 'account 2' }, 
    { id: 3, name: 'account 3' }, 
]); 

var balances = Rx.Observable.from([ 
    { account_id: 1, balance: 100 }, 
    { account_id: 2, balance: 200 }, 
    { account_id: 3, balance: 300 }, 
]); 

に応じて二つの流れ(参加)マージする必要があります。

var results = [ 
    { id: 1, name: 'account 1', balance: 100}, 
    { id: 2, name: 'account 2', balance: 200}, 
    { id: 3, name: 'account 3', balance: 300}, 
]; 

はRxJsと、この可能ですか?

私はプレーンなjs/lodashなどでこれを行う方法を知っています。私の場合、Angular Httpモジュールからこれらのストリームを取得しているので、私はこのケースでRxJsの利点を得ることができるかどうかを質問しています。

+1

ドゥ両方のストリームが終了したり、時間の経過とともにそれらを構築したりすると結果が欲しいですか? – Maxime

+0

サンプルコードを投稿すると、問題をよりよく理解するのに役立ちます。提示されているように、ストリーム内から行うのではなく、配列に直接結合しない理由は明確ではありません。しかし、とにかく、あなたが言及する参加をすることは可能です。 Cf。 http://stackoverflow.com/questions/43332674/rxjs-to-combine-attributes-from-triples-to-a-table/43333630#43333630構造を繰り返し作成する方法を示します – user3743222

+0

@Maxime、私の場合は完了後しかし、フロー中にそれを行う方法があれば、それは良いでしょう – amd

答えて

0

あなたのコメントの1つに、Accular Httpコール。

ので、代わりの:なぜ

var accounts = Rx.Observable.of([ 
    { id: 1, name: 'account 1' }, 
    { id: 2, name: 'account 2' }, 
    { id: 3, name: 'account 3' }, 
]); 

var balances = Rx.Observable.of([ 
    { account_id: 1, balance: 100 }, 
    { account_id: 2, balance: 200 }, 
    { account_id: 3, balance: 300 }, 
]); 

from 1つずつすべてのアイテムを放出するが、ofは配列全体を放出する

var accounts = Rx.Observable.from([ 
    { id: 1, name: 'account 1' }, 
    { id: 2, name: 'account 2' }, 
    { id: 3, name: 'account 3' }, 
]); 

var balances = Rx.Observable.from([ 
    { account_id: 1, balance: 100 }, 
    { account_id: 2, balance: 200 }, 
    { account_id: 3, balance: 300 }, 
]); 

私はむしろそれがあることを言うだろうあなたのhttpレスポンスは配列全体だと思います。

const { Observable } = Rx; 

// simulate HTTP requests 
const accounts$ = Rx.Observable.of([ 
    { id: 1, name: 'account 1' }, 
    { id: 2, name: 'account 2' }, 
    { id: 3, name: 'account 3' } 
]); 

const balances$ = Rx.Observable.of([ 
    { account_id: 1, balance: 100 }, 
    { account_id: 2, balance: 200 }, 
    { account_id: 3, balance: 300 } 
]); 

// utils 
const joinArrays = (accounts, balances) => 
    accounts 
    .map(account => Object.assign({}, account, { balance: findBalanceByAccountId(balances, account.id).balance })); 

const findBalanceByAccountId = (balances, id) => 
    balances.find(balance => balance.account_id === id) || { balance: 0 }; 

const print = (obj) => JSON.stringify(obj, null, 2) 

// use forkJoin to start both observables at the same time and not wait between every request 
Observable 
    .forkJoin(accounts$, balances$) 
    .map(([accounts, balances]) => joinArrays(accounts, balances)) 
    .do(rslt => console.log(print(rslt))) 
    .subscribe(); 

出力:

[ 
    { 
    "id": 1, 
    "name": "account 1", 
    "balance": 100 
    }, 
    { 
    "id": 2, 
    "name": "account 2", 
    "balance": 200 
    }, 
    { 
    "id": 3, 
    "name": "account 3", 
    "balance": 300 
    } 
] 

はここで働いてPlunkrです:https://plnkr.co/edit/bc0YHrISu3FT45ftIFwz?p=preview

EDIT 1:何あなたはおそらく達成したいことである、と述べた

結果を構成するために配列を処理することは、おそらくパフォーマンスのための最良のアイデアではなく、配列を返す代わりに、キーのIDを持つオブジェクトを返そうとする可能性があります。あなたは、単にfindBalanceByAccountId機能を削除して、より高速なアプリ(ここでの唯一の変更されたコード)を持っているかもしれません。この方法で

const balances$ = Rx.Observable.of({ 
    1: { account_id: 1, balance: 100 }, 
    2: { account_id: 2, balance: 200 }, 
    3: { account_id: 3, balance: 300 } 
}); 

// utils 
const joinArrays = (accounts, balances) => 
    accounts 
    .map(account => Object.assign(
     {}, 
     account, 
     { balance: balances[account.id].balance } 
    )); 
+0

ありがとうございます、残念ながらあなたの仮定は正しくありません:実際には、オブジェクトのストリームとしてデータがありますObservable ' Observable ' – amd

0

あなたがidで二つの項目に参加するGROUPBY演算子を使用することができます。

Rx.Observable.merge(accounts, balances.map(({account_id, balance})=>({id: account_id, balance}))) 
.groupBy(accountInfo => accountInfo.id) 
.flatMap(accountInfo$ => accountInfo$.scan((acc, info) => Object.assign(acc, info), {}) 
    .filter(accountInfo => accountInfo.name && accountInfo.balance) 
    .take(1) 
).subscribe(console.log) 
関連する問題