更好的RxJS序列方式

时间:2017-06-28 05:28:59

标签: angular sequence rxjs5

我如何简化这个序列,因为我似乎正在重新创造厄运的金字塔,并且应该有更多的Rx-y方式。

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,否则返回false。

基本上

  • 进行初始XHR通话
  • 获得结果时
  • 使用第一次通话的结果
  • 进行第二次XHR通话
  • 获得结果时
  • 做出最终决定。

我所询问的内容与我在SO上看到的内容之间的区别有两个:

  • 这些异步操作按顺序且不重叠
  • 第一个响应中的有效负载用于第二个

另一个类似的情况可能是(1)获取一个令牌,然后(2)在后续请求中使用该令牌。

2 个答案:

答案 0 :(得分:0)

如果要链接可观察量,请使用switchMapflatMap。此外,您不需要使用Observable.create()故意创建另一个Observable,因为您的this.getAccounts()已经返回了一个observable。

这应该更简洁:

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
        }
    })

答案 1 :(得分:0)

鉴于签名:

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可以产生的值的数量,我们阻止自己发出true(来自mergeMap)和false(默认来自concat)作为排放。