当前位置: 首页 > 知识库问答 >
问题:

Angular 6/Rxjs-基本操作方法:可观察到的成功、错误、最终

何涵衍
2023-03-14

我正在最新的Angulal6上构建一个架构,从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();
    

    既然我们必须用管道来完成,我也可以用管道来完成所有的事情,我认为最好的做法是让所有的事情都按同样的顺序进行。但是现在我们必须扔一些东西,叫做“的”(不太容易理解),我不喜欢这样。

    半管道,所以我尝试另一个想法,只使用我需要的管道(完成),我保留订阅回调。

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

    但是,嗯。这不是有点落后吗?我们仍然有没有实际名称的回调,并且在读取处理和错误之前完成。奇怪的

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

    我的需求很简单:
    1。我想处理从服务获取的数据
    2。我想获取错误以便向用户显示
    3。我想停止在调用之前刚启动的加载微调器,或者在第一次调用完全成功或出错后再调用一次(我真的希望最后一次)

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

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

  • 共有3个答案

    钱澄邈
    2023-03-14

    我认为正确的方法是使用可观察的函数:下一步,err,完成。
    这里有一个如何触发完整函数的例子。
    假设我们有行为主体对象:

    let arr = new BehaviorSubject<any>([1,2]);
    

    现在让我们假设我们想要订阅它,如果我们得到“finish”值,我们就想要完成。

    let arrSubscription = arr.asObservable().subscribe(
      data => {
          console.log(data)
          if(data === 'finish') {
            arr.complete()
          }
      },
      err => {
          console.log(err)
      },
      () => {
          console.log("Complete function triggered.")
      }
    );
    arr.next([3,4])
    arr.next('finish')
    arr.next([5,6])
    

    控制台日志为:

    [1,2]
    [3,4]
    finish
    Complete function triggered.
    

    因为我们触发了完整的函数,我们的行为主体旁边的最后一个.不会被触发,因为err和完整的函数是订阅的终止符。
    这只是一个你如何触发完整函数的例子,从这里你可以做任何你想做的事情。

    萧懿轩
    2023-03-14

    可观测的subscribe方法接受3个可选函数作为参数

    • 第一个处理由可观察事件引发的数据的人
    • 第二个用于处理任何错误(如果发生)
    • 第三个是在完成可观察的任务时做某事

    所以,如果我理解正确,你想要的可以用这样的代码来实现

    this.service.getAll()
    .subscribe(
        data => this.onSuccess(data),
        error => this.handleError(error),
        () => this.onComplete()
    );
    

    考虑使用HTTP调用的可观测值可以在您想重试时看到好处(参见<代码>重试< /代码>运算符),以备有竞争条件(通过使用<代码>开关图< /代码>运算符)。我认为这些是Angular团队选择http客户机采用这种方法的主要原因。

    一般来说,我认为有必要开始了解可观察对象是如何工作的,一些最重要的操作符(除了上面提到的那些操作符外,我首先想到的是mergeMapfilterreduce,但还有很多其他操作符)非常重要,因为它们可以显著简化异步模式中的许多任务非阻塞环境,例如浏览器(例如节点)。

    岳泉
    2023-03-14

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

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

    这并不完全正确。每个可观察的可以发送零个或多个下一个通知和一个错误完成通知,但绝不能两者兼而有之。例如,当成功进行HTTP调用时,您将有一个下一个和一个完成通知。在错误HTTP请求中,您将只有一个错误通知,仅此而已。看http://reactivex.io/documentation/contract.html

    这意味着你永远不会有一个可观察的发射错误完成

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

    所以你的第二个例子是正确的。我理解它看起来很奇怪,你包括finize之前订阅,但事实上,每个排放从源观察首先从上到下,它到达订户那里,如果它的错误完成通知它触发从下往上(以相反的顺序)处置处理程序,此时调用finize。看https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subscriber.ts#L150-L152

    在您的示例中,使用finalize与将dispose处理程序自己添加到订阅对象中相同。

    const subscription = this.service.getAll()
      .subscribe(
        (data) => this.onSuccess(data),
        (error) => this.handleError(error)
      );
    
    subscription.add(() => this.stopLoading());
    
     类似资料:
    • 我正在努力理解rxJs观察者/可观察的。 我有一个Angular应用程序,其中一个服务创建一个可观察的: 闲聊服务ts: 当聊天室中收到消息时。服务ts,消息(假定)是多播的: 两个组件以这种方式订阅可观察对象: 问题:只有一个(最后一个订阅的)收到消息。 问:我如何配置可观察到多播到所有订阅者?

    • 因此,我有一个NgRx选择器,它返回一个带有一系列触点的可观测值。我想映射这个流,对于每个联系人数组,映射每个联系人,并向Github发出Http请求以获取他们的配置文件图像,并将其附加到联系人对象。然而,我不知道如何做到这一点,而不以一系列的可观测数据结束。 下面是我尝试过的,但这不起作用。 下面是我收到的错误消息: 如有任何建议,将不胜感激!

    • 我对Observables和RxJs是新手,我想对回报进行调整。如果第一个选择器返回某个值,我希望第二个选择器可以观察到。但是如果第一个选择器没有返回那个特定的值,我想返回false,而不是(false)。我已经走了这么远,但这返回了一个可观察的结果

    • 我试图将一个角度函数转换为可观察模式,因为它的当前实现与它有一些异步性。为了讨论这个问题,我们举一个简单的例子。 可以通过以下方式将其转换为使用可观察对象: 我所面临的问题(据我所知)是针对无法访问内部选择语句的情况。 如果使用常规主题,订阅函数肯定不会得到任何值,因为事件的顺序是: 函数被调用 主题已创建 值已设置 调用函数订阅,因此仅在此事件发生后获取值 如果使用了BehaviorSubjec

    • Let’s expand our example and do something a little more with our stream: 除了简单地遍历异步集合之外,我们还可以执行其他操作,例如过滤或映射,以及RxJS API中定义的更多操作。 这是一个与可迭代模式的桥梁,让我们将它们概念化为集合。 这里有两个真正有用的数组操作 - map 和filter。 这些做什么呢? 请注意链接函数