熟悉 Promise 踩到的坑

阅读时长 7 分钟读完

什么是 Promise?

Promise 是一种处理异步编程的方式,它可以让我们更加简单地处理回调函数带来的困扰。

Promose 对象有三种状态:Pending(进行中)、Resolved(已完成)和Rejected(已失败)。当 Promise 的状态从 Pending 转变为 Resolved 或 Rejected 时,Promise 对象会调用对应的回调函数。这些回调函数被称作“成功回调”和“失败回调”。

Promise 的使用

创建 Promise

创建 Promise 的方式非常简单,使用 Promise 构造函数即可:

Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。resolve 表示异步操作成功,reject 表示异步操作失败。

调用 Promise

调用 Promise 的方式也很简单:

then 方法接受两个参数:成功回调和失败回调。当 Promise 对象状态从 Pending 转变为 Resolved 时,会调用成功回调;当状态从 Pending 转变为 Rejected 时,会调用失败回调。

处理 Promise

Promise 的回调函数是异步执行的,所以我们可以使用链式调用来处理多个异步操作:

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

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

then 方法会返回一个新的 Promise 对象,所以我们可以链式调用多个 then 方法。如果其中任何一个 Promise 对象的状态变为 Rejected,就会调用 catch 方法。

Promise.all

如果我们有多个异步操作,需要等待所有异步操作完成后再进行下一步操作,可以使用 Promise.all:

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

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

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

Promise.all 方法接受一个 Promise 对象数组作为参数,当所有 Promise 对象状态都变为 Resolved 时,会返回一个 Promise 对象,并将所有 Promise 对象的结果封装在一个数组中。

Promise 的坑点

Promise 的错误处理

在 Promise 中,一旦 catch 方法被调用,Promise 的状态会从 Pending 转变为 Resolved。所以,如果在 catch 中抛出异常,将无法被 catch 处理。

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

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

如上代码中,如果在第一个 catch 方法中抛出异常,它不会被捕获,而是会被第二个 catch 方法捕获。因为第一个 catch 方法抛出的异常没有被 catch 捕获,所以 Promise 的状态变为了 Resolved。

Promise 的嵌套问题

在 Promise 中,可以使用 Promise.all 等方式来解决 Promise 的嵌套问题。但是在实际开发中,有些异步操作的执行时间不可预知,如果直接使用 Promise.all 来等待所有异步操作完成,可能会出现等待时间过长的情况。

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

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

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

如上代码中,promise1 的异步操作执行时间为 2 秒,promise2 的异步操作执行时间为 3 秒。虽然可以使用 Promise.all 来等待两个异步操作执行完成,但是这样会等待 3 秒钟,造成页面等待时间过长的情况。

对于这种情况,我们可以使用 Promise.race 来解决,它会等待数组中任意一个 Promise 对象的状态变化。所以,当其中任何一个异步操作执行完成时,就会执行相应的回调函数。

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

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

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

如上代码中,使用 Promise.race 来等待异步操作执行完成,只需要等待 2 秒钟就可以得到第一个异步操作的结果。

总结

在使用 Promise 的过程中,需要注意错误处理和嵌套问题的解决。错误处理可以使用 catch 方法来捕获异常,但是需要注意 catch 方法抛出异常的问题。嵌套问题可以使用 Promise.all 来解决,但是需要注意等待时间过长的问题,可以使用 Promise.race 来解决。

如果你的代码中有类似的问题,希望本文对你有所帮助。

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

纠错
反馈