Node.js中的 “for await …of “语句的简单解释。

微信扫一扫,分享到朋友圈

Node.js中的 “for await …of “语句的简单解释。

嘿,你们好!

几个月前,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 Worldn" });
}

突然,当看到第4行的 await
调用在 for
之后,但在 (const req of s)
之前时,我的眼睛就 “那是什么?”?

我从来没有见过这样的东西,我的第一个想法是 “这是一个非常酷和奇怪的事情,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风格。

然而,如果你想知道我的诚实和个人意见,我还没有遇到过 “这是迭代器的一个伟大的用例 “的情况。

无论如何,让我们回到我们文章的主题:我们还需要在for循环中添加 await什么?

异步迭代器

顾名思义,异步迭代器是我们在上面的例子中所做的异步版本。

想象一下,我们不是返回一个随机数,而是返回承诺。那会是怎样的呢?

如果我们把上面的例子改成这样,它就会是这样的。

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;
}
})();

变化有哪些?

  1. 我们首先将Symbol属性改为 “asyncIterator”,而不仅仅是 “iterator”。
  2. 我们把 “next “方法做成了一个异步函数。
  3. 我创建了simulateDelay函数,该函数返回一个承诺,在给定时间后解析给定值。
  4. 我们在for循环中加入了 await
  5. 我们把循环放在Inmediately调用的函数表达式里面,是为了不出现顶层 await调用的问题。(注意:在Node.js 14+版本中不再需要这个功能)

于是我们做了一个简单的程序,能够对一个对象进行迭代,以异步的方式获取其元素。

如果你知道除了主页上的小deno例子之外,还有其他的异步迭代器的实现,请发邮件给我,或者在下面留言

微信扫一扫,分享到朋友圈

Node.js中的 “for await …of “语句的简单解释。

三星发布Galaxy S20 FE粉丝版:屏幕拉直、5G 4750元起

上一篇

RocketMQ系列:rocketmq运维控制台使用详解(全网独家)

下一篇

你也可能喜欢

Node.js中的 “for await …of “语句的简单解释。

长按储存图像,分享给朋友