如何在 Promise 链式调用中正确使用 await?

阅读时长 4 分钟读完

Promise 是一种用于异步编程的技术,它允许我们在异步操作完成之后继续执行代码。而 Promise 链式调用则是 Promise 异步编程的常用方式。在 Promise 链式调用中,我们可能会用到 async/await 关键字以帮助我们更方便、更简单地管理 Promise 对象。但是,如果我们不正确地使用 await,就可能会遇到一些问题。那么,如何在 Promise 链式调用中正确使用 await 呢?

await 的原理

异步函数中的 await 关键字实际上是让 JavaScript 引擎先执行后面的表达式,再将结果交给 await,然后在将控制权转交回代码执行者。也就是说,await 实际上会将其后面的表达式转换为 Promise 对象,再确保这个表达式完全执行完毕,然后将该值带入 await 之后的逻辑中。

await 和 Promise 链

首先,了解 await 的基本语法是必要的:

通过使用上面的结构,我们可以将一个 Promise 异步函数转换为一个类似于同步函数的形式。这非常方便,因为避免了在代码中使用回调函数。而在一个 Promise 链中,我们可以使用 await 去等待前一个操作的完成,然后才能继续执行下一个操作。简而言之,使用 await 去等待上一个操作就是 await 的主要功能。

在实际使用 await 时,我们要记住一些细节:

  • 在一个 async 函数中使用 await
  • 在一个 Promise 链的末尾是一个同步函数:
  • 在一个 Promise 链中使用 await,将会阻塞其他的操作直到前一个操作完成。

常见错误

以下是使用 await 的常见错误:

没有使用 await

如果我们在一个异步函数中没有使用 await,那么这个函数就不会等待异步操作完成。在下面的例子中, foo() 返回的是一个 Promise 对象,它实际上不会等待异步操作完成:

多次使用 await

如果我们在一个 Promise 链中多次使用 await,那么将无法从「异步等待」状态中推出。因此,下面的代码有问题:

在这个例子中,当我们等待 asyncFunc1(),它是可行的。但是当我们等待 asyncFunc2() 时,将会出现问题。在等待 asyncFunc2() 的过程中,asyncFunc1() 已经完成,并且 await 现在将继续等待它完成。但是,如果 asyncFunc1() 在等待第二个 Promise 完成后再次被调用,在等待第二个 Promise 的时候就会出现问题。

所以正确的做法是:

使用 Promise.all() 可以保证并行的执行所有异步操作,并且让所有的 Promise 共同等待它们所有的异步操作完成。

不需要 wait 的

有时我们会在一个 Promise 链中的某个点使用 await,但是实际上这并没有必要。在这种情况下,这将会使代码变慢,并加重我们的负担。例如:

在这个例子中,我们可以用 then() 的链式操作而不是 await 表达式。完成这些操作后,res 将会传递给 then() 中的代码。将上述代码重写如下:

这将避免明显的错误以及潜在的待遇问题。

结论

正确使用 await 可以大幅提高 Promise 链式调用的编写效率,但是深入理解 await 的原理,以避免常见错误和问题,才能更好地写出高效、稳定的异步代码。

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

纠错
反馈