Rxjs解析一个可观察和合并结果

时间:2018-01-16 19:54:42

标签: rxjs observable ngrx angular2-observables redux-observable

我在订阅一个observable数组时遇到了问题。 在我的例子中,我有一个ID数组,我需要从我的状态获取所有ID,将所有结果合并到一个observable中并订阅该observable。 我需要我的订阅者最终会获得一系列已解析的observable。

此外,我需要保持此订阅处于打开状态,因此,如果我的内部可观察内容之一发生更改,我的订阅者将收到通知。

这是我的代码:

getTransactionsByIDs(transactionsIDs){
return Observable.of(transactionIDs
  .map(transactionID => this.getTransactionByID(transactionID)));
}

this.transactionsService.getTransactionsByIDs(transactionsIDs)
.subscribe(transactions=>{
 ....
})

订阅者功能中上述代码的结果是一系列未解析的商店。

如何解决每个商店并将它们全部组合在一起?

我还尝试在transactionsID上使用Observable.from()将每个ID转换为observable,然后解析它。它工作正常,但我的订户分别收到每个ID的通知。如果有办法批处理所有Observable.from()结果(并保持订阅打开),请告诉我。

这是我的Observable.from()的样子:

getTransactionsByIDs(transactionsIDs){
return transactionIDs
  .mergeMap(transactionID => this.getTransactionByID(transactionID));
}

this.transactionsService.getTransactionsByIDs(Observable.from(transactionsIDs))
.subscribe(transactions=>{
 ....
})

感谢。

2 个答案:

答案 0 :(得分:5)

我认为你想要的是combineLatest。它不会发出任何值,直到所有内部可观察量发出至少一个值。之后,每次从内部可观察者之一发出新的发射时,它将从所有发出的最新发射。

以下是一些阅读材料:learnrxjs.io/operators/combination/combinelatest.html

以下是一个例子:

function getTransactionByID(transactionId) {
  let count = 0;
  return Rx.Observable.of(transactionId)
    .delay(Math.random() * 4000)
    .map(x => `${x}: ${count++} `)
    .repeat();
}

function getTransactionsByIDs(transactionsIDs){
  return Rx.Observable.combineLatest(transactionsIDs.map(transactionID => getTransactionByID(transactionID)));
}

const transactionsIDs = [1,2,3];
getTransactionsByIDs(transactionsIDs)
  .take(10)
  .subscribe(x => { console.log(x); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.min.js"></script>

take(10)只是让示例永远不会继续下去。

答案 1 :(得分:2)

您想要的行为并不完全清楚,但您最有可能想要forkJoinzipcombineLatest

forkJoin

当所有可观测量完成后,发出一个包含每个可观察量的最后一个值的数组。

拉链

订阅所有内部可观察者,等待每个人发出一个值。一旦发生这种情况,将发出具有相应索引的所有值。这将持续到至少一个内部可观察完成。

combineLatest

当任何observable发出值时,从每个值发出最新值。

示例:

getTransactionsByIDs(transactionsIDs) {
  const transactions = transactionIDs.map(transactionID => this.getTransactionByID(transactionID));
  return Observable.forkJoin(...transactions); // change to zip or combineLatest if needed
}


this.transactionsService.getTransactionsByIDs(['1', '2', '3'])
  .subscribe(([first, second, third]) => {
    console.log({ first, second, third });
  });