随着 JavaScript 的不断发展,ES9 (ECMAScript 2018)已经正式发布。其中最令人激动的新特性之一就是异步迭代(asynchronous iteration)。
异步迭代允许我们为异步的数据结构(例如,通过网络连接获取的 JSON 对象)创建一个迭代器。通过使用异步函数和 for-await-of 循环,我们可以以同步方式遍历异步结构的每个元素而无需等待整个数据结构下载。
迭代器
在深入讨论异步迭代之前,让我们首先简要回顾一下迭代器(iterator)。
迭代器是一种用于遍历集合的接口,其中包括一个 next() 方法,该方法在每次调用时返回集合的下一个值。每个返回值由两个属性组成:value 和 done。value 表示下一个值,done 表示是否已到达集合的末尾。
我们可以使用 for-of 循环遍历可迭代对象(iterable),例如数组、Set 或 Map。在迭代期间,for-of 循环会自动调用该对象的迭代器。
传统迭代的问题
传统的迭代不适用于异步数据结构的迭代。例如,我们可以将以下代码作为对比:
for (let item of fetch('https://example.com/data')) { console.log(item); }
代码中,我们试图使用 for-of 循环遍历异步获取的数据,但这是无效的。每次调用 fetch() 都会返回一个 Promise,而不是一个可迭代对象。因此,for-of 循环会尝试在 Promise 上调用迭代器,但这会导致 TypeError。
在过去,我们必须使用回调函数或 Promise 链在异步结构中进行迭代,这往往非常笨重。在 ES9 中,我们终于可以通过异步迭代来简化这个过程。
异步迭代
使用异步迭代,我们可以为异步数据结构创建一个迭代器,该迭代器将 Promise 对象转换为可迭代对象。每次调用迭代器的 next() 方法时,Promise 将异步地解析。这意味着我们可以使用 for-await-of 循环同步地遍历异步数据结构的每个元素,而不必担心整个数据结构的下载。
首先,让我们创建一个异步生成器函数。异步生成器函数是一种函数,可通过使用 async 和 yield* 关键字实现异步数据结构的生成器。
async function* getData() { const response = await fetch('https://example.com/data'); const json = await response.json(); for (let item of json) { yield item; } }
在代码中,我们创建了一个异步生成器函数,该函数在解析 JSON 数据之后返回一个迭代器。这个迭代器可以在 for-await-of 循环中使用,以便同步地遍历我们在 fetch() 中异步获取的数据。
接下来,我们可以使用 for-await-of 循环来遍历异步数据结构的每个元素:
(async function() { for await (let item of getData()) { console.log(item); } })();
在代码中,我们使用了一个自动执行的异步函数,其中使用了 for-await-of 循环来遍历异步数据结构中的所有元素。在调用迭代器的 next() 方法时,将异步获取每个元素的值。
结论
异步迭代是 JavaScript 中强大而令人兴奋的新特性之一。这种方式简化了不同异步数据结构的迭代,带来了更少的繁琐和冗长的代码。我们希望这篇文章能够帮助你理解异步迭代的工作原理,并启发你构建更强大和高效的异步代码。
参考示例如下:
// javascriptcn.com code example // 异步生成器函数 async function* getData() { const response = await fetch('https://jsonplaceholder.typicode.com/users'); const json = await response.json(); for (let item of json) { yield item; } } // 异步循环 (async function() { for await (let item of getData()) { console.log(item.name); } })();
该示例从“https://jsonplaceholder.typicode.com/users”中获取 JSON,然后使用异步迭代功能遍历并打印所有用户的名称。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6735aa0d0bc820c5824fc3b3