ECMAScript 2019 新特性详解:for-await-of
在 JavaScript 中,异步编程是非常重要的。但是,随着 JavaScript 的异步变成方式越来越多,代码显得越来越凌乱。于是的,for-await-of 循环,成为了 ECMAScript 2019 新特性中的一员,它可以让我们更方便地在异步循环中使用 async/await,有效地减少了代码的嵌套层数,使代码更加简洁易读。
在介绍 for-await-of 循环之前,我们先了解一下 for...of 循环,它是 ES6 中引入的一种语法。循环一个 iterable 对象,比如数组、字符串等等。下面是一个 for...of 循环的示例代码:
let numbers = [1, 2, 3]; for (let number of numbers) { console.log(number); }
输出结果:
1 2 3
而 for-await-of 循环,则是 ES2018 中引入的。它的作用是循环异步的可迭代对象(async iterator)。比如 Promise.all() 中传入的 Promise 数组,就是一个异步的可迭代对象。下面是一个 for-await-of 循环的示例代码:
-- -------------------- ---- ------- ----- -------- --------- - --- -------- - - ------------------- ------------------- ------------------- -- --- ----- ---- ------- -- --------- - --------------------- - - ----------展开代码
输出结果:
1 2 3
可以看到,结果和 for...of 循环是一样的。只不过这里的可迭代对象是一个异步的可迭代对象。for-await-of 循环使得我们在异步循环中使用 async/await 更加方便了。
再来看一个例子,以此更深入的理解 for-await-of 的用法:
-- -------------------- ---- ------- ----- -------- --------- - --- -------- - - ------------------- --- --------------- -- ------------- -- ----------- ------- ------------------- -- --- ---- ------- -- --------- - --- ------ - ----- -------- ---------------------- -------- - - ----------展开代码
这段代码里面,我们使用了 for...of 循环和 await 的方式,遍历了一个 Promise 数组,并且将每个 Promise 解析后输出。正常情况下,这段代码是可以正常工作的。但是,如果我们把 for...of 改成 for-await-of,我们会发现代码会报错:
-- -------------------- ---- ------- ----- -------- --------- - --- -------- - - ------------------- --- --------------- -- ------------- -- ----------- ------- ------------------- -- --- ----- ---- ------- -- --------- - --- ------ - ----- -------- ---------------------- -------- - - ----------展开代码
输出结果:
(node:4894) UnhandledPromiseRejectionWarning: TypeError: promises[1][Symbol.asyncIterator] is not a function (node:4894) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
我们知道,Promise 是一个可迭代的对象,但是它并没有实现 Symbol.asyncIterator 这个方法,所以使用 for-await-of 循环来遍历 Promise 数组会报这个错误。
为了修复这个问题,我们需要使用 Promise.all() 将可迭代对象转换成一个异步的可迭代对象。修改代码如下:
-- -------------------- ---- ------- ----- -------- --------- - --- -------- - - ------------------- --- --------------- -- ------------- -- ----------- ------- ------------------- -- --- ----- ---- ------- -- ---------------------- - ---------------------- --------- - - ----------展开代码
输出结果:
Result: 1 Result: 2 Result: 3
可以看到,代码又可以正常工作了。这就是 for-await-of 循环的使用场景。
总结一下,for-await-of 循环可以循环异步的可迭代对象,可以有效地简化代码的嵌套层数,更方便地使用 async/await,并且适用于遍历一个异步迭代器。当遍历的对象本身就是异步迭代器时,直接进行 async/await 将报错,此时应该使用 Promise.all() 方法将可迭代对象转化成异步可迭代对象。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64eb68c4f6b2d6eab35f98d1