【问题标题】:Finalize is not called after error in Angular 8 app在 Angular 8 应用程序中出错后不会调用 Finalize
【发布时间】:2019-10-31 07:26:59
【问题描述】:

我正在尝试在 Angular 8 中构建一个 Angular 应用程序,我从后端获取一个 Observable 并希望订阅它。这是我已经拥有的代码:

this.employeesService.getEmployees$()
      .pipe(
        tap(employees => {
          this.employees = employees;
          console.log(this.employees.length);
        }),
        catchError(err => this.error = err),
        finalize(() => {
          console.log(this.error);
          this.isOperationInProgress = false;
        })
      )
      .subscribe();
this.employeesService.getEmployees$()

这个函数返回一个 Observable,我想用它做很多事情。

当我尝试访问后端但它处于脱机状态时,我没有得到任何函数的返回值。所以这是我的问题:

发生这种情况时,我会尝试调用 finalize 函数。但是这个函数在出错后不会被调用。

有什么办法解决这个问题吗?

【问题讨论】:

  • catchError 必须返回 observable
  • @DamianPioś 所以我可以把我的 this.employees 还给那里?
  • tap 不会在发生错误时触发,所以employees 将是undefined,你可以像of(error.message)一样返回。

标签: angular http rxjs


【解决方案1】:

感谢您的提问。

catchError()The official definition 运算符是:

通过返回新的 observable 或抛出错误来捕获要处理的 observable 上的错误。

或者换句话说,这个操作符的主要思想是在发生错误的情况下返回一个新的 observable。如果你愿意,我可以提供一个带有业务逻辑的代码示例。

finalize() operator 的想法是提供在 Observable 完成后启动副作用的可能性。因为错误还是刚刚完成。

因此,如果您想在 BE 服务不可用时显示错误消息,您的代码应该类似于:

this.isOperationInProgress = true;
// I do not recommend the '$' symbol for service methods. But, it's up to you
this.employeesService.getEmployees().pipe(
   tap(console.log),
   finalize(() => this.isOperationInProgress = false)
).subscribe(
    employees => this.employees = employees, 
    error => this.showErrorMesage(error.message)
)

如果您对更详细的解释感兴趣:这是一篇关于错误处理的精彩 blog 帖子

我希望它有用。我想听听您的任何反馈。祝你有美好的一天!

【讨论】:

  • 感谢您的回答。这也有效。我是否必须在this.showErrorMessage() 中返回一些东西?
  • 抱歉这么长的回答。如果您在 subscribe 方法中使用第二个参数捕获错误,您应该只提供带有签名 (e: error) => void 的回调。因此,此函数不应返回任何内容。祝你有美好的一天!感谢您的反馈。
  • 如果省略了 subscribe() 中的 error => {} 块,finalize() 会起作用吗?例如。我只对积极的结果感兴趣,所有其他结果都应该在 finalize() 中处理。谢谢
  • @tillias 不确定我是否正确理解了您的观点。是的,即使subscribe() 中的错误部分丢失,它也应该可以工作。但是,如果您不订阅,则不会执行整个管道。例如。请求不会发送。附:如果你想尝试一些类似这个假设的东西,你可以在 StackBlitz with rxjs playground 上查看它。谢谢你的提问。
【解决方案2】:

RxJS 更习惯将结果存储在订阅中,而不是使用tapcatchError 将中间值存储为“副作用”。这主要是因为副作用更难单独测试。

this.employeesService.getEmployees$()
.pipe(
    take(1)
)
.subscribe(
    employees => {
        this.employees = employees;
        this.isOperationInProgress = false;
    },
    error => {
        this.error = error;
        this.isOperationInProgress = false;
    }
); 

蜜蜂说的;你的 finalize 没有被调用的原因是因为 catchError 应该总是返回一个 Observable,而不是 void

【讨论】:

  • 那么,如果我将返回语句添加到我的 catchError 中,它会起作用吗?然后我应该返回一个新的 Observable 还是返回员工?
【解决方案3】:

我自己做的。我只是更改了 catchError 子句和 finalize 子句。

this.employeesService.getEmployees$()
      .pipe(
        tap(employees => {
          this.employees = employees;
          console.log(this.employees.length);
        }),
        finalize(() => {
          this.isOperationInProgress = false;
        }),
        catchError(err => {
          this.error = err;
          return this.employees;
        })
      )
      .subscribe();

但感谢您的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-26
    • 2020-08-17
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-07
    相关资源
    最近更新 更多