rxjs - RxJS:即使在源 observable 上使用了 `shareReplay()`,`throwError()` 也会为每个 observable 单独执行
问题描述
我在 observable ( ) 上使用 RxJSshareReplay()
运算符在courses$
其他两个 observable (beginnerCourses$
和advancedCourses$
) 之间共享 observable 流。它工作正常,单个 API 调用响应在两个可观察对象之间共享成功。
但是,当涉及到错误时,这些 observable 不会共享错误,并且会在浏览器控制台中看到错误被抛出两次。运营商不shareReplay()
也分享错误吗?这是预期的行为吗?
const http$ = createHttpObservable('/api/courses');
const courses$ = http$
.pipe(
map(res => res['payload'] ),
shareReplay(),
catchError(err => {
return throwError(err);
})
);
this.beginnerCourses$ = courses$
.pipe(
map(courses => courses
.filter(course => course.category === 'BEGINNER')));
this.advancedCourses$ = courses$
.pipe(
map(courses => courses
.filter(course => course.category === 'ADVANCED')));
}
解决方案
我认为这是预期的行为,有点出乎意料的是您遇到了 2 个不同的错误。
shareReplay
ReplaySubject
在数据消费者和数据生产者之间放置 a 。当错误通知到达时,ReplaySubject
in use 将向所有注册订阅者发送相同的错误通知:
error(err: any) {
if (this.closed) {
throw new ObjectUnsubscribedError();
}
this.hasError = true;
this.thrownError = err;
this.isStopped = true;
const { observers } = this;
const len = observers.length;
const copy = observers.slice();
for (let i = 0; i < len; i++) {
copy[i].error(err);
}
this.observers.length = 0;
}
但是在使用shareReplay
时,如果发生错误,当新订阅者即将订阅时,ReplaySubject
正在使用的将被另一个替换。说它正在被替换,这也需要重新订阅 source。
所以我认为所有订阅者都应该收到相同的错误通知,只要他们已经是ReplaySubject
订阅者列表的一部分。否则,当有新订阅者进来时,源将被重新订阅。
您可以做的是防止接收ReplaySubject
错误通知并允许其订阅者按原样接收它,是使用materialize
和dematerialize
运算符:
const courses$ = http$
.pipe(
materialize(), // Everything as a `next` notification
map(res => res['payload'] ),
shareReplay(),
dematerialize() // Back to the original event
);
使用这种方法,如果注册的订阅者收到错误通知,它将被取消订阅,这意味着它也将从ReplaySubject
订阅者列表中删除。但它ReplaySubject
仍然存在,并且不会在后续订阅者中被替换。
另外,我认为这是非常多余的:
catchError(err => throwError(err));
推荐阅读
- python - 随机 Tkinter 窗口放置不起作用
- python - 如何从 Python 中的类的静态方法输出?
- postgresql - postgresql:在 pl pgsql 中使用时间戳变量
- objective-c - 从 Objective-C 到 Swift 的代码转换中的无效重新声明
- python - 如果我们将子类中的超类构造函数作为第一行调用,这有关系吗?
- javascript - 我们如何从 JavaScript 访问 div?
- flutter - 如何让 Flutter 应用全屏显示?
- python - python - 如何在退出python中的tkinter窗口时使代码完全停止执行?
- javascript - 在下一个js中无法访问生产环境中的url路径
- javascript - 手动选择图像后图像幻灯片疯狂运行