Promise 使用中的常见误区

阅读时长 9 分钟读完

Promise 是 JavaScript 中处理异步编程的一种重要方式。相较于传统的回调函数,Promise 更为简洁、易于扩展和维护。但是在实际使用中,存在一些常见的误区,特别是对于初学者而言,需要引起重视。本文将介绍 Promise 使用中常见的误区,并提供相应的指导和示例代码。

一、对 Promise 链式调用的理解误区

在 Promise 官方文档中,我们看到了许多关于链式调用的使用方法:

这里的 job1job2job3 函数实现了异步逻辑的处理,同时返回一个 Promise 对象,然后通过 .then() 方法进行链式调用(可以继续使用 .catch() 处理错误)。关于 Promise 的链式调用还包括:

  • 单个 .then() 子句可以连接多个回调函数,但每个回调函数必须返回 Promise 对象。
  • .then() 子句本身也返回 Promise 对象,可以继续进行链式调用。
  • .then() 子句中的函数可以直接返回一个值,该值将用 Promise 对象作为参数执行。

然而,在实际使用过程中,可能产生以下的误区:

1. 不返回 Promise 对象

在链式调用的使用中,每个回调函数必须返回一个 Promise 对象,否则会中断整个链式调用。例如:

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

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

此时我们希望顺序输出:job finishedjob1 finishedjob2 finished。然而,由于第二个 .then() 子句中的回调函数没有返回一个 Promise 对象,导致第三个 .then() 子句不会被执行。正确的做法是在 job2 上返回一个 Promise:

2. 不用错误处理函数

Promise 在处理过程中,可以使用 .catch() 方法来捕获异常并进行处理。正确的写法是在链式调用的最后一处增加 .catch()

注意,如果在链式调用的每个子句中都使用了 .catch() 子句,实际上是没有必要的。在该子句之后的所有回调函数都会得到相应的错误参数。

3. 滥用 .then() 语法

.then() 关键字的作用是将程序在异步处理之后的下一步操作“挂起”,等待异步调用的结果出现后再继续进行。但是在使用 .then() 的过程中,一些开发者容易出现链式调用过于复杂或存在过多嵌套等问题,导致代码难以维护。应当合理运用 Promise 的应用场景和语法特点,保证代码的可读性和可维护性。

二、Promise.all 的使用误区

Promise.all() 是将多个 Promise 对象打包成一个 Promise 对象,全部处理完成后才触发后续操作,例如:

在使用 Promise.all() 的过程中,可能存在以下误区:

1. Promise.all 参数是空数组

如果传递给 Promise.all() 函数的参数是空数组,则会立即返回一个 resolved Promise 对象。这是因为这个 Promise 不包含任何等待的异步任务,所以不需要等待任何异步操作完成:

对于这个问题,实际上可以直接使用 Promise 对象作为参数:

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

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

2. Promise.all 中有 rejected Promise

如果 Promise.all() 中的任何一个 Promise 对象出现无法解决的问题,则整个方法将直接返回一个 rejected Promise 对象。这时,我们需要在 .catch() 部分获取错误信息:

3. Promise.all 中的 Promise 只要有一个完成就会返回

Promise.all() 的最终结果是由所有 promise 完成时产生的结果组成的数组。如果其中的任何一个 promise 被拒绝,那么调用 Promise.all() 的 promise 将被拒绝。因此,如果您有多个异步任务,其中一个完成时就可以处理结果,而其他不必等待,则不要使用Promise.all() 函数。

三、使用 async/await 时的误区

async 和 await 是 ES7/ES2017 标准中用于处理异步编程的新特性,在使用时也存在一些错误的使用方式:

1. 非异步操作调用 async/await

使用 await 关键字需要在异步函数中。否则,我们就会收到下面的错误:

正确的做法是在异步函数中调用 await

2. 忘了处理错误

使用 async/await 的代码段,需要使用 try-catch 语句来捕捉和处理错误。否则,异步调用的错误可能会直接结束程序的执行:

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

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

3. 不正确地编写异步函数

异步函数应该返回一个 Promise。如果它们没有返回一个 Promise,则执行将不会像预期一样正常工作:

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

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

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

正确的做法是在异步函数中使用 Promise 返回:

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

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

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

结论

Promise 是一种强大的异步编程方案,但在使用时需注意一些常见的错误。本文介绍了 Promise 中常见的误区,包括 Promise 链式调用的理解问题、Promise.all 的使用问题,以及 async/await 时的误区。正确地使用 Promise 不仅可以提供高效的异步处理能力,还可以提升代码的可维护性和可读性。

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

纠错
反馈