angular - Angular 6 / Rxjs - 如何基础:observables 成功,错误,最后
问题描述
我正在最新的 Angular 6 上构建一个架构,并且来自 AngularJS,有一些我无法解决的问题:HTTP 请求的基本处理。
所以,为了这个问题,假设我想要一个可观察的。因为它似乎是 Angular 的未来。
我从 AngularJS 中非常优雅的东西出发:
service.getAll()
.then(onSuccess) // I process the data
.catch(onError) // I do whatever needed to notify anyone about the issue
.finally(onFinally); // I stop the loading spinner and other stuff
现在在 Angular 6/RxJS 6 中,我不明白为什么一切都如此复杂而且看起来不正确。
我可以找到两种方法来做与上面相同的事情:
完整的管道
this.service.getAll() .pipe( map((data) => this.onSuccess(data)), catchError(error => of(this.handleError(error))), finalize(() => this.stopLoading()) ) .subscribe();
由于我们必须使用管道进行最终确定,所以我不妨对所有内容都使用管道,我认为将所有内容按相同顺序排列是更好的做法。但是现在我们必须抛出一些东西,叫做“of”(不太容易理解),我不喜欢这样。
半管道所以我尝试了另一个想法,只使用我需要的管道(最终确定)并保留订阅回调。
this.service.getAll() .pipe( finalize(() => this.stopLoading()) ) .subscribe( (data) => this.onSuccess(data), (error) => this.handleError(error) );
但是,好吧。是不是有点落后了?我们仍然有没有实际名称的回调,我们在读取处理和错误之前完成。诡异的。
所以有些东西我绝对不明白。而且我在网上找不到与这个基本问题相关的任何内容。您要么有人想要“成功并最终”,要么有人想要“成功和错误”,但没有人想要其中的 3 个。也许我太老了,我不了解新的最佳实践(如果是这样,请教育我!)。
我的需求很简单:
1. 我想处理从服务获取的数据
2. 我想获取错误以便显示给用户
3. 我想停止我刚刚在调用之前启动的加载微调器,或者一旦第一个电话完全成功或错误,再打一个电话(我真的想要一个 finally)
你如何使用 observable 处理基本的 HTTP 调用?
(我不想要任何.toPromise
东西,拜托,我想了解如何处理新东西)
解决方案
我认为有一个关键的误解:
您要么有人想要“成功并最终”,要么有人想要“成功和错误”,但没有人想要其中的 3 个。
这并不完全正确。每个 Observable 可以发送零个或多个next
通知和一个error
或complete
通知,但不能同时发送两者。例如,当进行成功的 HTTP 调用时,您将收到next
一则complete
通知。在错误的 HTTP 请求中,您将只有一个error
通知,仅此而已。见http://reactivex.io/documentation/contract.html
这意味着你永远不会有一个 Observable 同时发射error
和complete
。
然后是finalize
操作员。处理链时调用此运算符(也包括普通取消订阅)。换句话说,它在和通知之后被调用。error
complete
所以你的第二个例子是正确的。我知道你finalize
在订阅之前包含它看起来很奇怪,但实际上来自源 Observable 的每个发射首先从上到下到达订阅者,如果它error
或complete
通知它触发处理处理程序自下而上(以相反的顺序),此时finalize
叫做。见https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subscriber.ts#L150-L152
在您的示例中,使用finalize
与将处置处理程序自己添加到Subscription
对象中相同。
const subscription = this.service.getAll()
.subscribe(
(data) => this.onSuccess(data),
(error) => this.handleError(error)
);
subscription.add(() => this.stopLoading());
推荐阅读
- windows - 如果使用 AHK 打开,请关闭 Win10“开始菜单”?
- reactjs - React - 显示图像的正确路径
- javascript - 关于 Jenkins 产生 NAN% 和空报告 URL 的引诱报告
- python-3.6 - 当逗号后有/没有空格时,为什么 dateutil.parser('May 10, 2019') 返回不一致的年份值?
- azure - 在我的订阅中检查 azure 存储帐户中使用的总空间
- spring-boot - org.apache.kafka.common.errors.NotLeaderForPartitionException:此服务器不是该主题分区的领导者 - 继续出现
- google-analytics - 增强型电子商务无法识别内部促销视图对象
- amazon-web-services - 如何让 Docker Swarm 管理器使用 IAM 角色权限从 AWS ECR 中提取图像?
- c++ - 将向量传递给类的成员函数
- javascript - JS 中的神经网络不训练