我正在学习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调用完成之后,我找不到一种将所有结果都集中到一个位置的方法。
也许我从一开始就做错了,但是这部分似乎对我来说很好。
答案 0 :(得分:4)
最容易添加toArray()
:
from(apiCallIterator)
.pipe(
mergeMap(val => makeAnApiCall()),
toArray(), // collect all results
)
.subscribe(allResults => ...); // allResults.forEach(...) to iterate all results
您还可以使用forkJoin
,但是您必须事先准备所有Observables源的数组。但是,这只是您的选择。
答案 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&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&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/