分别要求第二个Observable调用RxJS concatMap订阅

时间:2018-08-20 01:40:31

标签: javascript angular typescript rxjs

我正在编写Angular 6应用。我希望它在路由更改以及有任何未决的http请求时显示加载动画。所以我有2个Observables看起来像这样。对于httpPendingRequests,我使用Angular的HttpInterceptor编写的计数器来实现;对于locationChanged,我已经订阅了Router的NavigationStart / NavigationEnd事件。

httpPendingRequests: BehaviorSubject<number>;
locationChanged: BehaviorSubject<boolean>;

我正在使用concatMap来订阅这两个Observable,代码如下:

this.locationChanged.pipe(
  concatMap(changed => {
    console.log('location change:' + changed);
    if (changed) {
      return this.httpPendingRequests;
    } else {
      return of(0);
    }
  }),      
  map(count => count > 0)
).subscribe(val => { 
  console.log('isloading: ' + val);
});

因此,我希望仅在更改位置以及有任何待处理的请求时,此命令才能将“正在加载”记录到控制台。在这种情况下它确实起作用。但是,我发现当只有待处理的http请求但位置未更改时,它还会记录“正在加载”消息。这让我感到困惑,我以为操作员正在确保可观察变量的订购顺序?如果第一个(位置更改)没有发出,那么第二个(待处理的请求)不应该被触发?我理解这个概念错了吗?

此外..我还尝试了其他方法来组合Observables,zip,forkJoin,combinateLatest-在我的情况下,它们都只触发一次订阅,因此我也不太确定出了什么问题。

很高兴在需要时提供更多信息。预先感谢

2 个答案:

答案 0 :(得分:0)

可以通过使用combineLatestmap运算符来解决。这是演示:https://stackblitz.com/edit/so-rxjs-concat

代码位于app.component.ts中。查看console.log的值以了解更多信息。

答案 1 :(得分:0)

您可能想看看使用BehaviorSubject的事实。

BehaviorSubject始终需要一个在创建时发出的值。这意味着locationChanged总是发出至少一个通知。

如果您更愿意使用Subject,则可以控制何时发出第一条通知。

在下面的示例中,直接从您的代码中获取的内容,由于locationChanged从未发出,因此您看不到任何记录。

const httpPendingRequests = new BehaviorSubject<number>(0);
const locationChanged = new Subject<boolean>();

locationChanged.pipe(
    concatMap(changed => {
      console.log('location change:' + changed);
      if (changed) {
        return httpPendingRequests;
      } else {
        return of(0);
      }
    }),      
    map(count => count > 0)
  ).subscribe(val => { 
    console.log('isloading: ' + val);
});

setTimeout(() => {
    httpPendingRequests.next(1);
}, 100);
setTimeout(() => {
    httpPendingRequests.next(2);
}, 200);
setTimeout(() => {
    httpPendingRequests.next(3);
}, 300);