Promise 中 catch 和 finally 的执行顺序问题详解

阅读时长 6 分钟读完

前言

在前端开发中,使用 Promise 是非常常见的异步编程方式。Promise 对象有三种状态:pending(进行中)、fulfilled(已完成)和 rejected(已失败)。

在使用 Promise 进行异步编程时,catchfinally 是两个重要的方法。它们可以在 Promise 对象的状态变为失败状态时执行一些操作,如捕获异常和处理资源的清理等。

但是,catchfinally 的执行顺序有一些细微的区别,特别是在异常处理时。

本文将详细解析 Promisecatchfinally 的执行顺序,帮助开发者更好地理解和应用 Promise

catch 和 finally 的基本用法

Promise 中,catch方法用于捕获 Promise 对象中的异常。当 Promise 对象的状态变为 rejected 时,catch 方法会被调用,并接收到一个参数,该参数表示抛出的异常信息。

下面是一个基本的 Promise 示例代码:

-- -------------------- ---- -------
----- ------- - --- ----------------- ------- -- -
  ------------- -- -
    ------------ -------
  -- -----
--

------------------- -- -
  ------------------
--

在上面的代码中,setTimeout 函数会在1秒后将 promise 的状态改为 rejected,并传递一个 Some Error 的信息。catch 方法会接收到该信息,并输出到控制台。

另外,finally 方法则会在 Promise 对象的状态变化时执行,不管状态是 fulfilledrejected,都会执行其中指定的回调函数。严格来讲,finally 并不是异常处理方法,而是指定在 Promise 对象状态变化时,必须要执行的操作。

下面是一个 finally 方法的示例代码:

-- -------------------- ---- -------
----- ------- - --- ----------------- ------- -- -
  ------------- -- -
    ------------------
  -- -----
--

------------------ -- -
  -----------------------
--

在上面的代码中,setTimeout 函数会在1秒后将 promise 的状态改为 fulfilled,将执行 resolve 函数。finally 方法会在 promiseresolve 后被执行,并输出 Complete 到控制台。

catch 和 finally 的执行顺序

因为 catchfinally 方法都是为了在 Promise 对象状态变化时执行特定的操作,开发者很容易将它们混淆,特别是在异常处理时。

下面我们就来详细探讨 catchfinally 的执行顺序:

如果在 Promise 对象状态变为 rejected 时没有 catch 函数

如果在 Promise 对象的执行过程中,没有使用 catch 方法进行异常捕获,那么默认情况下,Promise 对象会将异常抛出到上层调用栈。这种情况下,finally 方法依然会在 Promise 对象状态变化时调用。

下面是一个无 catch 函数的 Promise 示例代码:

-- -------------------- ---- -------
----- ------- - --- ----------------- ------- -- -
  ------------- -- -
    ------------ -------
  -- -----
--

------------------ -- -
  -----------------------
--

在上面的代码中,promise 对象被 reject 后,没有 catch 函数对异常进行捕获处理。在这种情况下,异常信息将被抛出,并打印到控制台。但是,finally 方法依然会在 Promise 对象状态变化时执行,并输出 Complete 到控制台。

如果在 Promise 对象状态变为 rejected 时有 catch 函数

如果在 Promise 对象的执行过程中,使用了 catch 函数进行异常捕获,那么在异常被处理后,finally 方法就会被调用。

下面是一个有 catch 函数的 Promise 示例代码:

-- -------------------- ---- -------
----- ------- - --- ----------------- ------- -- -
  ------------- -- -
    ------------ -------
  -- -----
--

-------
  ------------ -- -
    ------------------
  --
  ----------- -- -
    -----------------------
  --

在上面的代码中,promise 对象被 reject 时,catch 函数被调用并处理了异常信息。处理完成后,finally 方法依旧会被调用,并输出 Complete 到控制台。

如果在 catch 中抛出异常

catch 函数中可能会抛出新的异常。如果在 catch 函数中抛出了新的异常,新的异常在下一个 catch 函数中捕获,而不会被当前 finally 捕获。

下面是一个在 catch 函数中抛出异常的 Promise 示例代码:

-- -------------------- ---- -------
----- ------- - --- ----------------- ------- -- -
  ------------- -- -
    ------------ -------
  -- -----
--

-------
  ------------ -- -
    ------------------
    ----- --- ---------- -------
  --
  ------------ -- -
    ------------------
  --
  ----------- -- -
    -----------------------
  --

在上面的代码中,promise 对象被 reject 时,catch 函数捕获了异常并打印到控制台。在 catch 函数中,我们抛出了新的异常,但是该异常并不会被当前的 finally 捕获。这个新的异常会被下一个 catch 函数捕获,并打印到控制台。而 finally 方法依旧会被执行,并输出 Complete 到控制台。

一个技巧是,在 catch 函数中不要抛出异常,而只需要打印异常信息。这样可以避免新的异常抵消当前处理的异常。

总结

在本文中,我们介绍了 Promisecatchfinally 方法的基本用法,并详细讲解了它们的执行顺序。

catchfinally 方法都有一定的局限性,需要开发者根据具体场景来决定是否使用它们。此外,在使用 catch 函数时,还要注意不要在其中抛出新的异常,以免影响后续异常处理。

希望本文的内容能够帮助开发者更好地学习和应用 Promise,提升自己的编程能力。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64cdb4661519ea946c182ee2

纠错
反馈