我正在编写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-在我的情况下,它们都只触发一次订阅,因此我也不太确定出了什么问题。
很高兴在需要时提供更多信息。预先感谢
答案 0 :(得分:0)
可以通过使用combineLatest
和map
运算符来解决。这是演示: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);