在订阅上最终可观察到

Posted

技术标签:

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

根据this artcle,onCompleteonError函数subscribe是互斥的。

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

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

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

有什么想法吗?

【问题讨论】:

【参考方案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)
  );

【讨论】:

我在删除文件订阅后使用它来获取表数据,效果很好,谢谢!

以上是关于在订阅上最终可观察到的主要内容,如果未能解决你的问题,请参考以下文章

嵌套可观察订阅问题,无法取消订阅

可观察 - 多个订阅者

如果两个依赖路径改变为可观察的,则Knockout在单个动作上计算多次触发

订阅可观察到的Angular 8组件中的问题

我试图取消订阅一个可观察的角度但我收到错误,例如取消订阅不存在

可观察到的 forkJoin 没有触发