首页
学习
活动
专区
工具
TVP
发布

Node.js 中的异步生成器和异步迭代

生成器函数在 JavaScript 中的出现早于引入 async/await,这意味着在创建异步生成器(始终返回 且可以 的生成器)的同时,还引入了许多需要注意的事项。

今天,我们将研究异步生成器及其近亲——异步迭代。

注意:尽管这些概念应该适用于所有遵循现代规范的 javascript,但本文中的所有代码都是针对 Node.js 10、12和 14 版开发和测试的。

异步生成器函数

假设我们要在生成器函数中使用 ,只要需要用 关键字声明函数,Node.js 就支持这个功能。如果你不熟悉异步函数,那么请看 《在现代 JavaScript 中编写异步任务》一文。

下面修改程序并在生成器中使用 。

同样在实际工作中,你也不会这样做——你可能会 来自第三方 API 或库的函数。为了能让大家轻松掌握,我们的例子尽量保持简单。

如果尝试运行上述程序,则会遇到问题:

JavaScript 告诉我们这个生成器是“不可迭代的”。乍一看,似乎使生成器函数异步也意味着它生成的生成器是不可迭代的。这有点令人困惑,因为生成器的目的是生成“以编程方式”可迭代的对象。

接下来搞清楚到底发生了什么。

检查生成器

如果你看了Javascript 生成器[1]的可迭代对象。当对象具有 方法时,该对象将实现迭代器协议,并且该 方法返回带有 属性, 属性之一或同时带有 和 属性的对象。

如果用下面这段代码比较异步生成器函数与常规生成器函数返回的生成器对象:

则会看到,前者没有方法,而后者有。

这两个生成器对象都有一个 方法。如果修改测试代码来调用这个 方法:

则会看到另一个问题:

为了使对象可迭代, 方法需要返回带有 和 属性的对象。一个 函数将总是返回一个 对象。这个特性会带到用异步函数创建的生成器上——这些异步生成器始终会 一个 对象。

这种行为使得 函数的生成器无法实现 javascript 迭代协议。

异步迭代

幸运的是有办法解决这个矛盾。如果看一看 生成器返回的构造函数或类

可以看到它是一个对象,其类型或类或构造函数是 而不是 :

尽管该对象有可能不是可迭代的,但它是异步可迭代的。

要想使对象能够异步迭代,它必须实现一个 方法。这个方法必须返回一个对象,该对象实现了异步版本的迭代器协议。也就是说,对象必须具有返回 的 方法,并且这个 promise 必须最终解析为带有 和 属性的对象。

一个 对象满足所有这些条件。

这就留下了一个问题——我们怎样才能遍历一个不可迭代但可以异步迭代的对象?

for await … of 循环

只用生成器的 方法就可以手动迭代异步可迭代对象。(注意,这里的 函数现在是 ——这样能够使我们在函数内部使用 )

但是,这不是最直接的循环机制。我既不喜欢 的循环条件,也不想手动检查 。另外,  变量必须同时存在于内部和外部块的作用域内。

幸运的是大多数(也许是所有?)支持异步迭代器的 javascript 实现也都支持特殊的    循环语法。例如:

如果运行上述代码,则会看到异步生成器与可迭代对象已被成功循环,并且在循环体中得到了 的完全解析值。

这个 循环更喜欢实现了异步迭代器协议的对象。但是你可以用它遍历任何一种可迭代对象。

当你使用 时,Node.js 将会首先在对象上寻找 方法。如果找不到,它将回退到使用 的方法。

非线性代码执行

与 一样,  循环会将非线性代码执行引入程序中。也就是说,你的代码将会以和编写的代码不同的顺序运行。

当你的程序第一次遇到 循环时,它将在你的对象上调用 。

该对象将 一个 promise,然后代码的执行将会离开你的 函数,并且你的程序将继续在该函数之外执行

一旦你的 promise 得到解决,代码执行将会使用这个值返回到循环体

当循环结束并进行下一个行程时,Node.js 将在对象上调用 。该调用会产生另一个 promise,代码执行将会再次离开你的函数。重复这种模式,直到 Promise 解析为 为 的对象,然后在 循环之后继续执行代码。

下面的例子可以说明一点:

这段代码你用了编号的日志记录语句,可让你跟踪其执行情况。作为练习,你需要自己运行程序然后查看执行结果是怎样的。

如果你不知道它的工作方式,就会使程序的执行产生混乱,但异步迭代的确是一项强大的技术。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200828A0LNXO00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券