使用Observable.toPromise()进行全局错误处理

时间:2018-12-20 13:03:22

标签: javascript angular angular5

嗨,我正在使用angular 5,我正在为其编写一个全局处理程序,如下所示。

@Injectable()
export class ErrorsHandler implements ErrorHandler {
  constructor(
    private injector: Injector,
  ) { }


  handleError(error: Error | HttpErrorResponse) {
    const router = this.injector.get(Router);
    const zone = this.injector.get(NgZone);
    console.log('Here')
    console.log(error)

    if (error instanceof HttpErrorResponse) {

      // Client Error Happend
      zone.run(() => router.navigate(['/error'], { queryParams: { error: JSON.stringify(error) } }))

    } else {
      // Log the error anyway
      router.navigate(['/error'], { queryParams: { error: JSON.stringify({ message: 'Failed' }) } });
    }
  }
}

在“可观察的世界”中一切正常,即如果我像以下那样失败了http呼叫

fireServerError() {
    this.httpService
            .get('https://jsonplaceholder.typicode.com/1')
            .subscribe(data => console.log('Data: ', data));
  }

如果服务器调用失败,我将正确获得一个错误对象,如控制台映像所示

enter image description here

但是,如果我使用toPromise()将其更改为一个承诺,则可以代替

fireServerError() {
    this.httpService
            .get('https://jsonplaceholder.typicode.com/1')
            .toPromise();
  }

我得到以下字符串堆栈跟踪信息,而不是错误的对象本身

enter image description here

我在做什么错。在未处理的承诺被拒绝的情况下如何抛出/获取错误对象。请帮忙。我被困住了;

请找到stackblitz链接Here

1 个答案:

答案 0 :(得分:1)

使用.toPromise()后,实际上是将行为放入不同的执行上下文中(读为ECMAScript 10.4),这意味着必须在新的执行上下文中/周围处理错误,而不要使它们出错像您期望的那样在Angular中冒泡。

我不能说我完全遵循您的示例代码(fireServerError总是应该通过HTTP调用抛出错误吗?),但是看来您想尝试在没有本地错误处理的情况下执行Promise,而是从允诺气泡到角度错误处理都存在任何错误。我不确定我是否会建议这样做,我认为这是在本地处理承诺错误的最佳实践(即在创建承诺时使用Promise.prototype.catchtry/await/catch block)。

话虽这么说,错误处理当然是一个复杂的话题,如果您不愿意在全局级别处理所有错误,那么可以尝试使用全局窗口事件处理程序来捕获所有未处理的promise rejections和在那里处理它们:

window.addEventListener("unhandledrejection", event => {
  event.preventDefault(); // prevent the default promise rejection behavior
  console.error(event); // do whatever you want with the error
}, false);

MDN guide on promises也可能有助于清除某些内容,希望有帮助!