【问题标题】:Observable Finally on Subscribe在订阅上最终可观察到
【发布时间】:2017-04-04 02:14:01
【问题描述】:

根据this artcleonCompleteonError函数subscribe是互斥的。

意味着onErroronComplete 事件将在我的subscribe 中触发。
我有一个逻辑块,无论我收到错误还是成功完成信息流,都需要执行该逻辑块。

我查找了类似finally in python 的东西,但我发现的只是finally,它需要附加到我创建的可观察对象上。

但我只想在订阅时执行该逻辑,并且在流结束后,无论是成功还是出错。

有什么想法吗?

【问题讨论】:

    标签: javascript rxjs rxjs5


    【解决方案1】:

    我现在在 Angular 应用程序中使用 RxJS 5.5.7 并且使用 finalize 运算符对我的用例有一个奇怪的行为,因为在成功或错误回调之前被触发。

    简单示例:

    // Simulate an AJAX callback...
    of(null)
      .pipe(
        delay(2000),
        finalize(() => {
          // Do some work after complete...
          console.log('Finalize method executed before "Data available" (or error thrown)');
        })
      )
      .subscribe(
          response => {
            console.log('Data available.');
          },
          err => {
            console.error(err);
          }
      );
    

    我不得不在订阅中使用add 方法来完成我想要的。基本上是在成功或错误回调完成后的finally 回调。像 try..catch..finally 块或 Promise.finally 方法。

    简单示例:

    // Simulate an AJAX callback...
    of(null)
      .pipe(
        delay(2000)
      )
      .subscribe(
          response => {
            console.log('Data available.');
          },
          err => {
            console.error(err);
          }
      )
      .add(() => {
        // Do some work after complete...
        console.log('At this point the success or error callbacks has been completed.');
      });
    

    【讨论】:

    • 自发布此答案以来,finalize 运算符必须已更改。使用您发布的说明 finalize 运算符被过早调用的代码,它按预期工作。
    【解决方案2】:

    此运算符的当前“pipable”变体称为finalize()(从 RxJS 6 开始)。较旧且现已弃用的“补丁”运算符称为 finally()(直到 RxJS 5.5)。

    我认为finalize() 运算符实际上是正确的。你说:

    仅在我订阅时以及流结束后执行该逻辑

    我认为这不是问题。如果需要,您可以拥有一个 source 并在订阅之前使用 finalize()。这样你就不需要总是使用finalize()

    let source = new Observable(observer => {
      observer.next(1);
      observer.error('error message');
      observer.next(3);
      observer.complete();
    }).pipe(
      publish(),
    );
    
    source.pipe(
      finalize(() => console.log('Finally callback')),
    ).subscribe(
      value => console.log('#1 Next:', value),
      error => console.log('#1 Error:', error),
      () => console.log('#1 Complete')
    );
    
    source.subscribe(
      value => console.log('#2 Next:', value),
      error => console.log('#2 Error:', error),
      () => console.log('#2 Complete')
    );
    
    source.connect();
    

    这会打印到控制台:

    #1 Next: 1
    #2 Next: 1
    #1 Error: error message
    Finally callback
    #2 Error: error message
    

    2019 年 1 月:针对 RxJS 6 更新

    【讨论】:

    • 有趣的是,这是一种与 Promise 完全相反的模式,因为finally() 方法首先附加,订阅强制强制通过/失败。
    • 是的,这太糟糕了。有人会认为 finally 块将在您的代码中排在最后。
    • 我喜欢 Angular JS 的承诺系统......正如 d512 所说,我希望“终于”成为最后一个......根本不喜欢这个......
    • 从 RXJS 5.5 开始,“finally”不再是 Observable 方法。请改用“finalize”运算符: source.pipe(finalize(() => console.log('Finally callback'))).subscribe(...); github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md
    • finalize 的问题是它等待“complete()”调用。如果您希望在每次发射时都得到最终结果(如果可观察到的发射成功,请执行 a,如果出错,请执行 b 代替 .. 在这两种情况下,请执行 c )?
    【解决方案3】:

    唯一对我有用的是这个

    fetchData()
      .subscribe(
        (data) => {
           //Called when success
         },
        (error) => {
           //Called when error
        }
      ).add(() => {
           //Called when operation is complete (both success and error)
      });
    

    【讨论】:

    • 我在删除文件订阅后使用它来获取表数据,效果很好,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多