在 ES9 中,新增了 for await...of
循环语法来处理异步迭代器,极大地方便了前端开发者处理异步代码。本文将详细介绍这一语法,并通过实例代码进行演示,以帮助读者更好地掌握这一技术。
什么是 for await...of
循环
在 ES6 中,我们有 for...of
循环来遍历一个可迭代对象(如数组、字符串、Map、Set 等)中的每一个元素。而随着 JavaScript 的异步编程模式越来越流行,ES9 也新增了 for await...of
循环语法,用于遍历异步可迭代器(AsyncIterable)中的每一个迭代结果。
一个异步可迭代器是一个接受 Symbol.asyncIterator
键的属性,该属性值为一个返回异步迭代器(AsyncIterator)的函数。异步迭代器是一个包含 .next()
方法的对象,并返回一个 Promise,在迭代完成后会 resolve 该结果。
如何使用 for await...of
循环
下面是一个简单的示例代码,用于遍历一个异步可迭代对象(这里使用 fs.readdir
实现异步文件读取并返回文件名列表的逻辑):
// javascriptcn.com 代码示例 const fs = require('fs') async function readFileNames(dirPath) { const files = await fs.promises.readdir(dirPath) for await (const file of files) { console.log(file) } } readFileNames('/tmp')
在上面的代码中,我们首先使用 fs.promises.readdir()
方法读取指定路径下所有文件的文件名列表,该方法返回一个 Promise,因此我们使用 async/await
语法来获取迭代器的值。接着我们使用 for await...of
循环遍历这个列表,并输出每一个文件的文件名。
需要注意的是,在 for await...of
循环中,变量 file
的值并不是一个字符串或者数字,而是被异步迭代器后续迭代之后 resolve 出来的值,因此我们需要等待每一个迭代操作的完成。
for...of
和 for await...of
循环的对比
为了更好地理解 for await...of
循环的作用,我们现在来对比一下使用 for
和 for...of
循环、使用 for await
和 for await...of
循环时的区别。
首先,当我们使用 for
循环来遍历一个 Promise 时,会出现以下的问题:
const p = Promise.resolve([1, 2, 3]) for (const i of p) { console.log(i) }
上面的代码并不能正确输出数组 [1, 2, 3]
中的每一个元素,因为 Promise 实例没有实现迭代器协议。这时候,我们可以将 Promise 实例与 for...of
循环结合起来,将 Promise.resolve()
替换为 Promise[Symbol.iterator]()
:
const p = Promise.resolve([1, 2, 3]) for (const i of await p[Symbol.iterator]()) { console.log(i) }
在这个例子中,我们首先使用 Promise.resolve()
声明一个 Promise 对象,该对象返回一个包含数组 [1, 2, 3]
等数据的 resolved 状态的 Promise。接着,我们使用 await
操作符获取了一个迭代器,之后使用 for...of
循环遍历迭代器获取数组中的每一个元素。
然而,当我们在上述代码的基础之上尝试使用 for await
循环时,却会收到以下错误提示:
TypeError: p[Symbol.asyncIterator] is not a function
这是因为 p
并不是异步可迭代的,因此我们需要使用 await Promise.resolve()
来创建一个 promiseResolved 后的异步可迭代对象:
const p = Promise.resolve([1, 2, 3]) for await (const i of (await Promise.resolve(p))[Symbol.asyncIterator]()) { console.log(i) }
在这个例子中,我们首先使用 Promise.resolve()
创建一个 resolved 状态的 Promise,其中包含一个数组 [1, 2, 3]
。接着,我们使用 await
操作符获取该 Promise 的迭代器并使用 for await...of
循环遍历异步迭代器。当迭代器被迭代完成后,我们输出了数组中的每一个元素。
综上所述,for await...of
循环可以方便地遍历异步可迭代器,而 for
循环和 for...of
循环则无法直接处理异步迭代器。在实践中,我们需要注意异步代码的写法,使其符合异步编程模式及正确的语法规范。
总结
在本文中,我们学习了 ES9 中的 for await...of
循环,该语法用于处理异步迭代器,使开发者可以方便地处理异步代码。我们通过示例代码比较了使用 for
、for...of
、for await
和 for await...of
循环时的异同,并给出了正确的异步代码写法。
在实践中,我们需要特别注意异步代码的写法和语法规范,尤其需要慎重处理 Promise 对象的处理。通过掌握 for await...of
循环,我们可以更好地处理异步代码和迭代操作,提高代码的可维护性和安全性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/652ce7857d4982a6ebe6ff81