Promise 是一种用于异步编程的技术,它允许我们在异步操作完成之后继续执行代码。而 Promise 链式调用则是 Promise 异步编程的常用方式。在 Promise 链式调用中,我们可能会用到 async/await 关键字以帮助我们更方便、更简单地管理 Promise 对象。但是,如果我们不正确地使用 await,就可能会遇到一些问题。那么,如何在 Promise 链式调用中正确使用 await 呢?
await 的原理
异步函数中的 await 关键字实际上是让 JavaScript 引擎先执行后面的表达式,再将结果交给 await,然后在将控制权转交回代码执行者。也就是说,await 实际上会将其后面的表达式转换为 Promise 对象,再确保这个表达式完全执行完毕,然后将该值带入 await 之后的逻辑中。
await 和 Promise 链
首先,了解 await 的基本语法是必要的:
async function asyncFunction() { const result = await promise; // Code below will only execute when `promise` completes. return result; }
通过使用上面的结构,我们可以将一个 Promise 异步函数转换为一个类似于同步函数的形式。这非常方便,因为避免了在代码中使用回调函数。而在一个 Promise 链中,我们可以使用 await 去等待前一个操作的完成,然后才能继续执行下一个操作。简而言之,使用 await 去等待上一个操作就是 await 的主要功能。
在实际使用 await 时,我们要记住一些细节:
- 在一个 async 函数中使用 await
- 在一个 Promise 链的末尾是一个同步函数:
- 在一个 Promise 链中使用 await,将会阻塞其他的操作直到前一个操作完成。
常见错误
以下是使用 await 的常见错误:
没有使用 await
如果我们在一个异步函数中没有使用 await,那么这个函数就不会等待异步操作完成。在下面的例子中, foo() 返回的是一个 Promise 对象,它实际上不会等待异步操作完成:
async function example() { const promise = foo(); return promise; }
多次使用 await
如果我们在一个 Promise 链中多次使用 await,那么将无法从「异步等待」状态中推出。因此,下面的代码有问题:
async function example() { const result1 = await asyncFunc1(); const result2 = await asyncFunc2(); return result2; }
在这个例子中,当我们等待 asyncFunc1(),它是可行的。但是当我们等待 asyncFunc2() 时,将会出现问题。在等待 asyncFunc2() 的过程中,asyncFunc1() 已经完成,并且 await 现在将继续等待它完成。但是,如果 asyncFunc1() 在等待第二个 Promise 完成后再次被调用,在等待第二个 Promise 的时候就会出现问题。
所以正确的做法是:
async function example() { const [result1, result2] = await Promise.all([asyncFunc1(), asyncFunc2()]); return result2; }
使用 Promise.all() 可以保证并行的执行所有异步操作,并且让所有的 Promise 共同等待它们所有的异步操作完成。
不需要 wait 的
有时我们会在一个 Promise 链中的某个点使用 await,但是实际上这并没有必要。在这种情况下,这将会使代码变慢,并加重我们的负担。例如:
async function example() { const result = await asyncFunc().then(res => res + 1); return result; }
在这个例子中,我们可以用 then() 的链式操作而不是 await 表达式。完成这些操作后,res 将会传递给 then() 中的代码。将上述代码重写如下:
async function example() { const result = await asyncFunc() .then(res => res + 1) .catch(err => console.log(err)); return result; }
这将避免明显的错误以及潜在的待遇问题。
结论
正确使用 await 可以大幅提高 Promise 链式调用的编写效率,但是深入理解 await 的原理,以避免常见错误和问题,才能更好地写出高效、稳定的异步代码。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6730c020eedcc8a97c92d11e