RxJS序列更好的方法

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)在随后的请求中使用该令牌。

如果要链接可观察量,请使用switchMapflatMap。此外,您不需要故意使用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可以产生我们自己防止从发光(来自mergeMaptruefalse(从concat缺省值)作为排放。

+0

会不会多次调用accountaAreInCredit,每个账户一次? – IanT8

+0

鉴于'getAccounts()'返回的数组'Account'将它仅与阵列调用一次。在上面的示例中没有应用缓存,所以如果多次调用isEligibleForOffers(),所有代码将被多次执行。 –