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

Vik*_*iya 9 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' }) } });
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在 Observable 世界中一切正常,即如果我执行失败的 http 调用,如下所示

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

如果服务器调用失败,我会正确地得到一个错误对象,如控制台图像中所示

在此处输入图片说明

但是,如果我使用 toPromise() 将其更改为承诺,则不是这样,如下所示

fireServerError() {
    this.httpService
            .get('https://jsonplaceholder.typicode.com/1')
            .toPromise();
  }
Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明

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

请在这里找到stackblitz链接

Roc*_*Man 1

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

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

话虽这么说,错误处理当然是一个复杂的主题,如果您执意要在全局级别处理所有错误,那么您可以尝试使用全局窗口事件处理程序来捕获所有未处理的承诺拒绝并在那里处理它们:

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

MDN 关于承诺的指南也可能有助于澄清一些事情,希望有所帮助!