ES6异步迭代器

简单介绍

几个月前,Deno(一种Node.js的继任者)被发布,并在主页上找到了一些有关如何使用它的演示:

import { serve } from "https://deno.land/std@0.69.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of s) {
  req.respond({ body: "Hello World\n" });
}

突然我的眼睛转向“那是什么???” 在for后面但在第4行的(const req of)之前查看await调用时我从未见过这样的事情,我的第一个念头是“这是deno所做的一件很酷又奇怪的事情”……。
想象一下,当我阅读有关deno的更多信息时,我发现那小段代码实际上是有效的javascript,并且在Node.js中也是有效的,而我对此一无所知
那是什么 为什么我从未见过?我应该在哪里使用?我已经错过了吗?
如果您有相同的问题,那就好!
这篇文章将尝试回答所有这些问题!
第一件事:

迭代器

你见过这样的东西吗?

class RandomNumberGenerator {
  [Symbol.iterator]() {
    return {
      next: () => {
        return { value: Math.random() };
      },
    };
  }
}

如果您这样做了,那么对您很有帮助,您可以跳到下一部分!
如果还没有,那么让我们深入研究一下它在做什么:
这个类RandomNumberGenerator正在实现[Symbol.iterator]或者@@iterator方法(当通过Symbol属性定义方法时,我们用两个@@引用该方法)。
在类中定义[Symbol.iterator]@@iterator方法允许该类的实例对象进行迭代!
由于现在我们将该@@iterator方法定义为RandomNumberGenerator类的实例方法,因此该类的所有实例现在都是可迭代的。您现在可以通过运行以下代码对其进行测试:

class RandomNumberGenerator {
  [Symbol.iterator]() {
    return {
      next: () => {
        return { value: Math.random() };
      },
    };
  }
}

const rand = new RandomNumberGenerator();

for (const random of rand) {
  console.log(random);
  if (random < 0.1) break;
}

为了使一切正常,该@@iterator方法必须返回一个包含next方法的对象,并且该next方法需要返回一个具有value属性和done属性的对象。
value将包含返回的值,而done将是一个布尔值,如果将其设置为true,则将结束迭代。
虽然value是强制性的,但done可以如上述示例中那样省略(这使我们可以定义无限的可迭代对象)。
嗯不错!
现在,我们可以使事情变得反复无常!
什么时候有用?
我相信这在很大程度上取决于您正在创建的业务逻辑的类型。
例如,我极力推荐的《Node.js设计模式》一书给出了一个迭代矩阵元素(您可能已将其定义为数组数组)的示例。
我也相信本文重点介绍了一些不错的用法。它定义了一些非常酷的方法,看起来很像python风格。
但是,如果您要我的诚实和个人见解,我还没有遇到过这样的情况:“对于迭代器来说,这是一个很好的用例”。
无论如何,让我们回到本文的主题:将await添加到for循环中还需要什么?

异步迭代器

顾名思义,异步迭代器是我们在上面的示例中所做的异步版本。
想象一下,我们没有返回随机数,而是返回了promise。看起来怎么样?
如果我们更改上面的示例来做到这一点,它将看起来像这样:

const simulateDelay = (val, delay) =>
  new Promise((resolve) => setTimeout(() => resolve(val), delay));

class RandomNumberGenerator {
  [Symbol.asyncIterator]() {
    return {
      next: async () => {
        return simulateDelay({ value: Math.random() }, 200); //return the value after 200ms of delay
      },
    };
  }
}

const rand = new RandomNumberGenerator();

(async () => {
  for await (const random of rand) {
    console.log(random);
    if (random < 0.1) break;
  }
})();

有哪些变化?
我们首先将Symbol属性更改为asyncIterator而不是iterator
我们使该next方法成为异步函数。
我创建了simulateDelay函数,该函数返回一个promise,该promise将在给定的时间后解析给定的值。
我们在for循环中添加了await
我们将循环放入一个间接调用的函数表达式中,以免顶层等待调用出现问题。(注意:Node.js 14+版本不再需要此功能)
因此,我们制作了一个简单的程序,该程序能够迭代以异步方式获取其元素的对象。
如果您在首页上的小符号示例之外还知道异步迭代器的任何其他实现,请通过电子邮件将它们发送给我或在下面对其进行评论!

原文链接:https://www.mikealche.com/software-development/a-simple-explanation-of-the-for-await-of-statement-in-node-js