30 天 JavaScript 实战第 13 天 -- Promise 异步编程技巧 ES6 篇

前端开发中,异步编程是一项非常重要的技能,因为 HTML、CSS、JavaScript 等资源的文件加载、网络请求以及浏览器本身的事件都属于异步操作。在 JavaScript 中,我们可以使用回调函数来处理异步编程,但是这种方式十分容易产生“回调地狱”的问题,所以 ES6 引入了 Promise,它是一种更好的异步编程方式。在本篇文章中,我们将深入学习 Promise 的相关知识。

什么是 Promise?

Promise 是一个异步编程的解决方案,它解决了回调函数嵌套难以维护的问题。Promise 的实现遵循先定义后执行的原则,通过链式调用来实现多个异步任务之间的执行规则,使得代码更加简洁和可读。ES6 中引入了 Promise 对象,我们可以通过 new Promise() 来创建一个 Promise 对象,它有三种状态:Pending、Fulfilled 和 Rejected。

  • Pending:初始状态,即未处理状态。
  • Fulfilled:处理成功状态。
  • Rejected:处理失败状态。

当 Promise 的状态从初始状态到成功状态或者失败状态时,会触发对应的回调函数。因此,Promise 可以用于接收异步操作的结果,以便进一步处理。下面是一个基础的 Promise 示例代码:

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

上述代码中,Promise 的构造函数中定义了一个异步操作,即 1 秒后返回一个随机数。如果随机数大于等于 0.5,就调用 resolve 方法将 Promise 的状态设置为 Fulfilled,否则则调用 reject 方法将状态设置为 Rejected。

在 Promise 实例中使用 then 方法,第一个函数参数用于处理成功的结果,第二个函数参数用于处理失败的结果。

Promise 链式调用

Promise 还支持链式调用,可以优雅地处理多个异步操作的顺序。Promise 链式调用中,每一个 then 方法都执行一个异步操作,并以当前 Promise 对象的返回值作为下一个 Promise 对象的参数,我们可以在 then 方法中返回一个新的 Promise 对象。下面是一个 Promise 链式调用示例代码:

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

上面的例子中,第一个 then 方法执行的异步操作返回一个 Promise 对象,并在该 Promise 对象的回调函数中将随机数乘以 2,然后返回这个新的 Promise 对象。第二个 then 方法中拿到的值就是第一个 then 方法返回的 Promise 对象的值。如果其中任意一个 Promise 对象被拒绝,就会调用 catch 方法处理异常。

Promise.all() 方法和 Promise.race() 方法

Promise.all() 方法可以接收一个由多个 Promise 对象组成的数组作为参数,当它们都成功执行时,返回一个由所有 Promise 对象返回的结果组成的数组对象,其顺序与参数数组中的顺序相同。如果其中任意一个 Promise 对象被拒绝,就会立即触发 reject 状态。

下面是一个 Promise.all() 演示代码:

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

上述代码中,Promise.all() 接收一个由三个 Promise 对象组成的数组作为参数,由于其中一个 Promise 对象被拒绝,所以整个 Promise.all() 被拒绝。

Promise.race() 方法返回一个 Promise 对象,其状态由参数数组中的第一个已完成的 Promise 对象状态决定。如果参数数组中没有一个 Promise 对象被完成或者被拒绝,那么 Promise.race() 将会一直等待,直到仍处于 Pending 状态时才返回。

下面是一个 Promise.race() 演示代码:

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

在上面的例子中,由于 promise2 的等待时间更短,所有它最先执行完成,所以控制台将输出“Resolved: Promise 2”字样。

结论

通过本篇文章的学习,我们已经深入了解了 Promise 异步编程技巧的相关知识。Promise 可以优雅地处理异步编程问题,避免回调地狱问题的产生,同时还支持链式调用、Promise.all() 方法以及 Promise.race() 方法等操作,使得代码更加简洁、易读和可维护。在实际开发中,我们可以根据具体场景灵活使用 Promise 技术,以提升应用程序的性能和可靠性。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/67098418d91dce0dc87990a8