首页 > 解决方案 > 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 中,我不明白为什么一切都如此复杂而且看起来不正确。

我可以找到两种方法来做与上面相同的事情:

  1. 完整的管道

    this.service.getAll()
        .pipe(
            map((data) => this.onSuccess(data)),
            catchError(error => of(this.handleError(error))),
            finalize(() => this.stopLoading())
        )
        .subscribe();
    

由于我们必须使用管道进行最终确定,所以我不妨对所有内容都使用管道,我认为将所有内容按相同顺序排列是更好的做法。但是现在我们必须抛出一些东西,叫做“of”(不太容易理解),我不喜欢这样。

  1. 半管道所以我尝试了另一个想法,只使用我需要的管道(最终确定)并保留订阅回调。

    this.service.getAll()
    .pipe(
        finalize(() => this.stopLoading())
    )
    .subscribe(
        (data) => this.onSuccess(data),
        (error) => this.handleError(error)
    );
    

但是,好吧。是不是有点落后了?我们仍然有没有实际名称的回调,我们在读取处理和错误之前完成。诡异的。

所以有些东西我绝对不明白。而且我在网上找不到与这个基本问题相关的任何内容。您要么有人想要“成功并最终”,要么有人想要“成功和错误”,但没有人想要其中的 3 个。也许我太老了,我不了解新的最佳实践(如果是这样,请教育我!)。

我的需求很简单:
1. 我想处理从服务获取的数据
2. 我想获取错误以便显示给用户
3. 我想停止我刚刚在调用之前启动的加载微调器,或者一旦第一个电话完全成功或错误,再打一个电话(我真的想要一个 finally)

你如何使用 observable 处理基本的 HTTP 调用?

(我不想要任何.toPromise东西,拜托,我想了解如何处理新东西)

标签: angularrxjsobservablefinally

解决方案


我认为有一个关键的误解:

您要么有人想要“成功并最终”,要么有人想要“成功和错误”,但没有人想要其中的 3 个。

这并不完全正确。每个 Observable 可以发送零个或多个next通知和一个errorcomplete通知,但不能同时发送两者。例如,当进行成功的 HTTP 调用时,您将收到next一则complete通知。在错误的 HTTP 请求中,您将只有一个error通知,仅此而已。见http://reactivex.io/documentation/contract.html

这意味着你永远不会有一个 Observable 同时发射errorcomplete

然后是finalize操作员。处理链时调用此运算符(也包括普通取消订阅)。换句话说,它在和通知之后被调用。errorcomplete

所以你的第二个例子是正确的。我知道你finalize在订阅之前包含它看起来很奇怪,但实际上来自源 Observable 的每个发射首先从上到下到达订阅者,如果它errorcomplete通知它触发处理处理程序自下而上(以相反的顺序),此时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());

推荐阅读