Angular RxJS序列的更好方法

Angular RxJS序列的更好方法,angular,sequence,rxjs5,Angular,Sequence,Rxjs5,我如何简化这个序列,因为我似乎在重建厄运金字塔,应该有一个更Rx-y的方式 public isEligibleForOffers(): Observable<Boolean> { return Observable.create((observer) => { this.getAccounts().subscribe( (accounts) => { if (!this.accountsAre

我如何简化这个序列,因为我似乎在重建厄运金字塔,应该有一个更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);
                        }
                    );
                }
            });
    });
}
public IsEligibleFrofers():可观察{
返回可观察的。创建((观察者)=>{
这是.getAccounts().subscribe(
(账户)=>{
如果(!this.accountsAreInCredit(accounts)){
观察者:下一个(假);
}否则{
此.getOffers(帐户).订阅(
(数据:优惠)=>{
设isEligible=(data.qualified&&this.eligibleForAny(data)==true&&this.registeredForAny(data)!==true);
观察者:下一个(智能化);
}
);
}
});
});
}
我需要打一个XHR电话来获取一组帐户,如果这些帐户是信用帐户,则再打一个XHR电话来获取当前的优惠,如果用户有资格获得任何优惠,则返回true或false

本质上

  • 进行初始XHR调用
  • 当你有结果的时候
  • 使用第一次调用的结果进行第二次XHR调用
  • 当你有结果的时候
  • 做一些最后的决定
我所问的和我所看到的之间的区别有两个方面:

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

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

如果要链接可观察对象,请使用
switchMap
flatMap
。另外,您不需要使用
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);
    })
}

如果要链接观察对象,请使用
switchMap
flatMap
。另外,您不需要使用
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);
    })
}
签名:

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);
  }  
public IsEligibleFrofers():可观察{
返回此文件。getAccounts()
.filter(accounts=>this.accountsAreInCredit(accounts))
.合并地图(
accounts=>this.getOffers(accounts),
(账户、优惠)=>offers.qualified&&this.eligibleForAny(优惠)和&!this.registeredForAny(优惠))
)
.concat(接收可观察到的(假))
.采取(1)项措施;
}  
因此,如果
accountsAreInCredit
生成false,则流将变为空,然后我们使用
.concat
操作符将默认值
false
附加到流中

mergeMap
(又称
flatMap
)采用了一种方法,您可以将输出值映射到
IsEligibleFroffers
布尔值

最后,通过限制函数IsEligibleFroffers可以产生的值的数量,我们可以防止自己将
true
(来自
合并映射
)和
false
(来自
concat
的默认值)作为排放

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);
  }  
public IsEligibleFrofers():可观察{
返回此文件。getAccounts()
.filter(accounts=>this.accountsAreInCredit(accounts))
.合并地图(
accounts=>this.getOffers(accounts),
(账户、优惠)=>offers.qualified&&this.eligibleForAny(优惠)和&!this.registeredForAny(优惠))
)
.concat(接收可观察到的(假))
.采取(1)项措施;
}  
因此,如果
accountsAreInCredit
生成false,则流将变为空,然后我们使用
.concat
操作符将默认值
false
附加到流中

mergeMap
(又称
flatMap
)采用了一种方法,您可以将输出值映射到
IsEligibleFroffers
布尔值


最后,通过限制函数IsEligibleFrofers可以产生的值的数量,我们可以防止自己将
true
(从
合并映射
)和
false
(从
concat
)作为排放发出。

将不会多次调用AccountareInCredit,每个帐户一次?如果
getAccounts()
返回一个
account
数组,则该数组只调用一次。在上面的示例中没有应用缓存,因此如果多次调用
IsEligibleFrofers()
所有代码都将执行多次。accountaAreInCredit是否会被多次调用,每个帐户调用一次?如果
getAccounts()
返回一个
帐户的数组
,该数组只能调用一次。上面的示例中没有应用缓存,因此如果多次调用
IsEligibleFrofers()
,所有代码都将执行多次。