在 JavaScript 的异步编程中,async/await 已经成为了许多开发者的首选工具。然而,在实际开发中,异步操作往往不仅仅只有一个,更重要的是,它们之间的依赖关系也可能非常复杂。这时,异步操作的组合和串行化就成了诸多挑战之一。ES9 中的 for-await-of 语句,则为这一问题提供了更加简洁、直观的解决方案。
异步迭代器简介
在介绍 for-await-of 语句之前,我们需要先了解一下异步迭代器。题目中提到的 “异步迭代器”,其实就是要求一个对象必须具有该值(value)和下一个表达式的 Promise 对象(即 done)的迭代器,以支持异步迭代。异步迭代器是 ES2018 中首次提出的,它允许我们用异步的方式遍历异步数据结构(比如异步生成器、异步队列等)。
异步迭代器是一个对象,它具有一个带有 Symbol.asyncIterator 方法的属性。该方法返回另一个对象,它实现了 next 方法,该方法返回一个 Promise 对象,当这个异步对象完成时,它将包含 done 和 value 属性。
这个迭代器可以被 for-await-of 语句使用,这样我们就可以异步地迭代多个异步任务,而不需要使用回调函数或者像 Promise.all 这样的解决方案。
for-await-of 语句
for-await-of 语句是一种新的语法结构,它允许我们用异步的方式遍历支持异步迭代器的异步数据结构,例如,在一个 Blob 中作为可读流来读取数据,这是一个浏览器中的示例:
-- -------------------- ---- ------- ----- -------- ------------- - ----- -------- - ----- --------------------------------- ----- ------ - -------------------------- --- ----- - --- --- - ----- ------ - ----- ------ ------ - ----- -------------- -- ------ ------ ----- -- ------------- - - ------- - ------------------- - -
在上述代码中,我们使用 fetch API 获取一个 Blob,并通过可读流读取它的内容。在 while 循环内,我们使用 await 保证 current 的读取和 previous 的写入之间不会存在条件竞争 (race condition)。
这种技术使得异步代码的组合变得非常简单,而这是传统的回调函数方法,甚至是 Promise.then 方法无法做到的。
使用 Promise.all
与使用 Promise.all 不同,for-await-of 的一个重大优势在于它可以并行执行异步任务,并在每个任务完成时立即处理结果。
对于依赖于它们之前的结果的一系列异步操作,我们将不再需要使用 callback、Promise.all或其他的类似方法。
async function main() { for await (const content of readStream('https://foo.com/bar.txt')) { console.log(content); } }
在上述代码片段中,我们异步地遍历来自 URL 的内容,并在其加载时就立即处理结果。如果这个步骤因不同的 URL 间存在依赖关系而变得更加复杂,那么使用 for-await-of 将会更加方便而不需要嵌套回调或者使用 Promise.all 。
总结
ES9 中新增的 for-await-of 语句可以使得异步操作的组合变得更加简单和直观。它可以异步地遍历异步数据结构,例如异步生成器、异步队列等,并在每次操作完成后即时处理其结果。
这些变化涉及到很多细节,因此建议读者仔细阅读相关文档并尝试使用这种语法来实现更多复杂逻辑。
示例代码
-- -------------------- ---- ------- ----- --------- -------------- - ----- ------------------- ----- ------------------- ----- ------------------- - ----- -------- ------------- - --- ----- ------ ----- -- --------------- - ------------------- - -
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/651d0f2c95b1f8cacd4934f5