RxJS序列更好的方法
问题描述:
我该如何简化这个序列,因为我似乎正在重新创造厄运金字塔,并且应该有更多的Rx-y方式。RxJS序列更好的方法
public isEligibleForOffers(): Observable<Boolean> {
return Observable.create((observer) => {
this.getAccounts().subscribe(
(accounts) => {
if (!this.accountsAreInCredit(accounts)) {
observer.next(false);
} else {
this.getOffers(accounts).subscribe(
(data: Offers) => {
let isEligible = (data.eligible && this.eligibleForAny(data) === true && this.registeredForAny(data) !== true);
observer.next(isEligible);
}
);
}
});
});
}
我需要做一个XHR调用来获取帐户的集合,如果账户中的信用,使另一个XHR调用来获取当前的优惠活动,如果用户是适合任何报价返回true,否则假。
本质
- 作出初步XHR呼叫
- 当你有结果
- 请使用结果从第一个呼叫
- 当你有结果
- 第2个XHR呼叫做出最后的决定。
之间就是我要问什么,我已经看到了SO是双重的区别:
- 这些异步操作都在序列和非重叠
- 从第一个响应的有效载荷在第二个中使用
另一个类似的情况可能是(1)获取令牌,然后(2)在随后的请求中使用该令牌。
答
如果要链接可观察量,请使用switchMap
或flatMap
。此外,您不需要故意使用Observable.create()
创建另一个Observables,因为您的this.getAccounts()
已经返回可观察值。
这应该是更简洁:
public isEligibleForOffers(): Observable<Boolean> {
return this.getAccounts().switchMap(accounts => {
if (this.accountsAreInCredit(accounts)) {
return this.getOffers(accounts)
.map((data: Offers) => {
return (data.eligible && this.eligibleForAny(data) === true && this.registeredForAny(data) !== true);
})
}
//you can be explicit by returning a an Observable of false:
return Obersvable.of(false);
})
}
,你可以直接使用它像这样:
this.isEligibleForOffers()
.subscribe(flag => {
//flag is a boolean
if(flag){
//do something
}else{
//do something else
}
})
答
鉴于签名:
getAccounts(): Account[]
accountsAreInCredit(accounts: Account[]): boolean
getOffers(accounts: Account[]): Offers
可以按如下步骤你的函数模型:
public isEligibleForOffers(): Observable<Boolean> {
return this.getAccounts()
.filter(accounts => this.accountsAreInCredit(accounts))
.mergeMap(
accounts => this.getOffers(accounts),
(accounts, offers) => offers.eligible && this.eligibleForAny(offers) && !this.registeredForAny(offers))
)
.concat(Rx.Observable.of(false))
.take(1);
}
因此,如果accountsAreInCredit
产生错误,则流将变为空,然后我们使用.concat
运算符将默认值false
附加到流中。
的mergeMap
(又名flatMap
)需要一个optional argument resultSelector
中,所以我们把它们映射到isEligibleForOffers
布尔值,你可以映射输出值。
然后最终通过限制值的量的函数isEligibleForOffers
可以产生我们自己防止从发光(来自mergeMap
)true
和false
(从concat
缺省值)作为排放。
会不会多次调用accountaAreInCredit,每个账户一次? – IanT8
鉴于'getAccounts()'返回的数组'Account'将它仅与阵列调用一次。在上面的示例中没有应用缓存,所以如果多次调用isEligibleForOffers(),所有代码将被多次执行。 –