JavaScript Promise 异常捕获
2021-06-19

Promise 在前端编程中,越来越频繁地被使用了。作为 ES6 的核心功能之一,Promise 现在 基本上没有兼容性问题(除了 Promise.prototype.finallyPromise.allSettledPromise.any 这些比较新的 API)。而且,现在 async functions 写法越来越普遍,Promise 作为其背后的基础功能,自然需要各位前端更好地掌握了。

这里推荐 阮一峰老师ES6 入门,简洁明了,还举例说明,同时满足新手和专家不同的学习需求!👍👍👍

好了,进入主题:如何捕获 JS 中 Promise 的异常?

一般 JS 中异常捕获都是使用 try…catch 语句,而 Promise 中如果出现异常,一般都是 reject(),然后在 Promise 链的末尾 Promise.prototype.catch 里处理异常。

Promise Chain

Promise 也可以使用 Promise.prototype.finally 或者使用 JS 原生的 try...catch 语句达到抛出异常的目的。

最佳实践

根据 MDN 的文章 推荐,一般 Promise 链的最佳实践满足以下三个条件:

  1. 内链返回新的 Promise
  2. 避免不必要的嵌套;
  3. 使用 catch 中止 Promise 链。

反例 🙁:

1
2
3
4
5
6
// Bad example! Spot 3 mistakes!
doSomething().then(function(result) {
doSomethingElse(result) // Forgot to return promise from inner chain + unnecessary nesting
.then(newResult => doThirdThing(newResult));
}).then(() => doFourthThing());
// Forgot to terminate chain with a catch!

正确姿势 🙂:

1
2
3
4
5
6
7
doSomething()
.then(function(result) {
return doSomethingElse(result);
})
.then(newResult => doThirdThing(newResult))
.then(() => doFourthThing())
.catch(error => console.error(error));

总结:

  • Promise.prototype.catch 可以捕获 Promise 中所有的异常,包括 reject 掉的、或者抛出的异常;以下两种写法其实是等效的:
    1
    2
    3
    new Promise((resolve, reject) => {
    throw new Error("Whoops!");
    }).catch(alert); // Error: Whoops!
    1
    2
    3
    new Promise((resolve, reject) => {
    reject(new Error("Whoops!"));
    }).catch(alert); // Error: Whoops!
  • 当我们明确知道哪里会出现异常,知道如何处理异常,请时刻牢记使用 Promise.prototype.catch 来捕获/分析/记录异常;如果我们不知道捕获到的异常种类(比如编程错别字导致的),那就重新抛出异常;
  • 当然,如果发生了无法预料到的异常,那我们也可以不使用 Promise.prototype.catch
  • 任何情况下,我们都应该监听 unhandledrejection 事件,跟踪未捕获的异常并通知给用户(也可能是我们的服务器),这样的话我们的应用才不会“死”。

不同点

  1. reject 只能用在 Promise 回调函数里,而抛出 (throw) 异常则可以使用在任何 try...catch 语句或者 Promise 中;
  2. reject 异常之后,方法内的函数会继续执行,而抛出 (throw) 异常则会立刻终止执行;
  3. reject 可以用在 Promise 的同步/异步回调函数里,而抛出 (throw) 异常只能用在同步回调函数里。

参考链接

本文链接:
content_copy https://zxs66.github.io/2021/06/19/JavaScript-Promise-error-handling/