使用 Promise 实现异步流程控制

阅读时长 6 分钟读完

前端开发中,异步操作非常常见,例如 AJAX 请求、定时器、读写本地存储等等,这些操作都是需要一定时间才能完成的。在异步操作中,我们通常需要依赖回调函数来处理异步结果。然而,随着业务逻辑的复杂度提升,经常会出现回调嵌套的情况,使得代码难以维护且容易出错。而 Promise 正是一种解决异步流程控制问题的有效方式。

Promise 简介

Promise 是 ECMAScript 6 引入的一种异步编程的解决方案,它从语言层面提供了一种更合理、更标准的异步处理方式,让异步代码更易理解和维护。在 Promise 中,异步操作的结果并非通过回调函数获取,而是使用 Promise 实例的状态来获取。Promise 可以看作是对异步操作的封装,它将异步操作封装为一个对象,使得整个异步操作可以像同步操作一样执。

Promise 可以分为三个状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。只有当 Promise 状态从 pending 变为 fulfilled 或 rejected 时,才会导致状态的不可变。

Promise 的使用

Promise 的基本用法

在 Promise 中,使用 Promise 构造函数创建一个 Promise 实例,然后使用 then 方法指定 Promise 异步操作成功时的回调函数,使用 catch 方法指定 Promise 异步操作失败时的回调函数。示例如下:

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

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

上述示例代码中,myPromise 是一个 Promise 实例,它的异步操作是通过 setTimeout 函数模拟的延时操作。在 setTimeout 回调函数中,如果生成的随机数大于 5,就调用 resolve 方法将 Promise 状态变为 fulfilled,同时可以传入一个参数作为异步操作成功的返回值;否则调用 reject 方法将 Promise 状态变为 rejected,同时也可以传入一个参数作为错误信息。

myPromise 对象上可以使用 then 方法添加一个异步操作完成后的回调函数,在该回调函数中可以使用异步操作的返回值。如果异步操作失败,可以使用 catch 方法指定一个错误回调函数。根据 Promise 的状态,thencatch 方法只会执行其中之一。

Promise.all 方法

在实际开发中,通常需要执行多个异步操作,等待所有异步操作完成后再做一些处理。Promise.all 方法可以将一组 Promise 实例当做单个 Promise 实例处理,当所有 Promise 实例都成功时,Promise.all 才会成功,且返回值是所有 Promise 实例返回值组成的数组,否则只要有一个 Promise 实例失败,Promise.all 就会失败,且返回值是失败的 Promise 实例的错误信息。示例如下:

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

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

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

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

上述示例代码中,p1p2p3 分别是三个异步操作所对应的 Promise 实例,使用 Promise.all 方法将三个 Promise 实例放在一个数组中传入,然后使用 then 方法指定 Promise.all 异步操作成功后的回调函数,在回调函数中可以使用所有 Promise 实例的返回值。

Promise.race 方法

如果异步操作中只有一个 Promise 实例完成就可以了,那么使用 Promise.race 方法可以实现这一需求。与 Promise.all 不同的是,Promise.race 只要有一个 Promise 实例改变状态,它就会改变自身状态,且该 Promise 实例返回的值会传给 Promise.race 异步操作成功时的回调函数。示例如下:

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

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

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

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

上述示例代码中,p2 是一个明显的失败状态的 Promise 实例,使用 Promise.race 将三个 Promise 实例传入,然后使用 thencatch 方法处理异步操作成功和失败的情况。

总结

Promise 是一种有效的异步流程控制的解决方案,它支持将异步操作封装为对象,并提供了更为规范的处理方式。在实际开发中,使用 Promise.all 和 Promise.race 方法组合多个异步操作可以提高代码逻辑的可读性和可维护性。在使用 Promise 时,需要注意异常处理,避免出现未捕获的 reject 状态导致程序异常的情况。

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

纠错
反馈