如何合并多个可观察到的RxJS的结果?

时间:2018-07-11 16:01:57

标签: javascript rxjs

我正在学习RxJS,并试图用之前的Promise替换一些代码,但是我一直在努力寻找正确的方法来组合可观察对象。

我有一个调用多个API的代码,并且每个API调用都执行相同的代码。而且,在完成API调用之后,我还有一些其他代码只能执行一次,并且只能执行一次。我用Promises做到了这一点,我做了多个Promises,对于每个Promise我都执行相同的代码,在Promise.all()上我只执行其他代码。

所以我试图用RxJS做到这一点:

var apiCallIterator = ["id1", "id2", id3];
var apiCallObservable = from(apiCallIterator)
  .pipe(
    mergeMap(apiCallIterator => {
      return makeAnApiCall();
    })
   );

apiCallObservable.subscribe({
next: value => {
 // do some code for each API call
},
error: () => {
 // api call failed
}
})

这对于我的任务的第一部分工作正常,它将在每次API调用完成后执行相同的代码。但是在所有API调用完成之后,我找不到一种将所有结果都集中到一个位置的方法。

也许我从一开始就做错了,但是这部分似乎对我来说很好。

4 个答案:

答案 0 :(得分:4)

最容易添加toArray()

from(apiCallIterator)
  .pipe(
    mergeMap(val => makeAnApiCall()),
    toArray(), // collect all results
  )
  .subscribe(allResults => ...); // allResults.forEach(...) to iterate all results

您还可以使用forkJoin,但是您必须事先准备所有Observables源的数组。但是,这只是您的选择。

https://stackblitz.com/edit/rxjs6-demo-qbvhjh?file=index.ts

答案 1 :(得分:2)

使用forkJoin,您可以实现这一目标

forkJoin是一个运算符,它接受任意数量的Observable,可以将其作为数组或直接作为参数进行传递。如果没有提供输入Observables,则结果流将立即完成。

forkJoin将等待所有传递的Observable完成,然后它将发出一个数组,其中包含来自相应Observable的最后一个值。因此,如果将n个Observable传递给运算符,则结果数组将具有n个值,其中第一个值是第一个Observable发出的最后一个值,第二个值是第二个Observable发出的最后一个值,依此类推。

答案 2 :(得分:1)

我认为您需要为此使用forkJoin运算符。

  

当您有一组可观测值和   只关心每个的最终发射值。一个常见的用例   因为这是如果您希望在页面加载时发出多个请求(或   其他事件),并且只希望在响应有   被所有人接受。这样类似于您的使用方式   无极。   https://www.learnrxjs.io/operators/combination/forkjoin.html

对于您的代码:

<FIXML r="20030618" s="20040109" v="4.4" xr="FIA" xv="1" xmlns="http://www.fixprotocol.org/FIXML-4-4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.fixprotocol.org/FIXML-4-4 https://optionsclearing.com/components/docs/membership/dds_ref/fia_1_1/fixml-main-4-4-FIA-1-1.xsd">
  <Batch>
    <SecList ListTyp="109" ListID="20175" BizDt="2017-12-07">
      <SecL Ccy="USD">
       <Instrmt Desc="iShares S&amp;P 100 ETF" SecTyp="OPT" SubTyp="ETO" Sym="OEF" Mult="100.0">
         <AID AltID="00013" AltIDSrc="RBHP"/>
       </Instrmt>
       <InstrmtExt>
         <Attrb Typ="101" Val="1.0000"/>
         <Attrb Typ="108" Val="1.0000"/>
       </InstrmtExt>
       <Undly Desc="iShares S&amp;P 100 ETF" Px="117.110000" Ccy="USD" Sym="OEF" ID="464287101" Src="1"/>
       <Stip Typ="RBHMIN" Val="2.500"/>
       <Stip Typ="CPMMIN" Val="3.750"/>
      </SecL>
   </SecList>
  </Batch>
</FIXML>

答案 3 :(得分:0)

您可以zip()全部使用它们,它们只会在所有可观测对象完成后才发出。

var apiCallIterator = ['id1', 'id2', 'id3'];

var apiCallObservable = zip(apiCallIterator.map(id => makeAnApiCall(id)))
  .subscribe({
    next: value => {
      // do some code for each API call
    },    
    error: () => {    
      // api call failed    
    }    
  })

makeAnApiCall(id) {
    return from(id).pipe(tap(() => {
     // do some code for each API call
    }));
}

也是学习rxjs的好网站-https://www.learnrxjs.io/