【问题标题】:Some practical example of asynchronous iteration(for-await-of) in action?异步迭代(for-await-of)的一些实际示例?
【发布时间】:2021-07-10 04:53:18
【问题描述】:

我知道asynchronous iteration 是什么。但是自从 MDN 和 node.js 10 在 2018 年推出它以来,我还没有看到它的实际用途,例如它会更好地解决什么样的问题? A common example我看到是把回调fs.createReadStream改写成for await (const chunk of stream)

Another example我能想到的就是按顺序发送分页请求。

但这两个例子不足以说服我使用for-await-of。我只是想不出我有一系列承诺需要一个一个解决它们的场景。

那么有人可以举一些使用异步迭代比不使用它更好地解决问题的实际例子吗?

【问题讨论】:

  • 我知道你的意思,就像回调地狱一样,异步事物依赖于另一个异步事物的结果。但我的问题是我想不出一个场景,我可以事先得到所有的承诺,然后一个一个地等待它们。
  • @danh 检查我在这里得到的答案github.com/tc39/proposal-async-iteration/issues/135
  • "我有一个 promises 数组的场景" - 当你已经拥有一个数组中的所有 promises(固定数量)时为时已晚;在这种情况下,you should not use for await … of。异步迭代仅在promise 一个接一个创建的情况下才有用,例如当它取决于前一项的结果时,它允许您开始处理第一个而不看到结束。
  • "这些例子不足以说服我使用for-await-of" - 你能告诉我们如何为没有for await … of 的人编写代码吗?也许这样更容易解释差异。但是,是的,它主要只是语法糖,您可以通过使用 await getNext() 手动迭代结构来编写任何这样的循环 - 就像 for … of 只是语法糖一样,就像每个 for 循环都可以重写为 while .
  • @Qiulang 因为承诺不是从外部解决的,所以它们不会“在您等待它们时开始解决” - 您执行的任务在您创建承诺时开始,承诺只代表结果。所以“一一解决”是没有意义的。您只能“逐一创建它们”。

标签: javascript node.js async-await es6-promise


【解决方案1】:

我只是通过引用@Bergi 的 cmets 和我从https://github.com/tc39/proposal-async-iteration/issues/135 得到的 cmets 来给出答案。如果没有答案,我的问题将被自动删除,因为它已被否决。

@Bergi 来自他的回答 https://stackoverflow.com/a/60707105/301513

for await ... of 在生成序列本身时很有用 异步(并且它的长度事先不知道 消费者)。一个完美的例子是从 api。不太完美的是从大目录中读取文件 - 虽然可以分两步编写该代码(获取一个数组 文件名,然后迭代),有时你更喜欢 api 表面 将它们打包在一起:一个异步迭代器,你总是 获取文件名和内容。

https://github.com/tc39/proposal-async-iteration/issues/135给出了一个从大目录读取文件的例子,

import fs from "fs/promises";

async function* findAllFiles(directory: string) {
    const dirEntries = await fs.readdir(directory, { withFileTypes: true });
    for (const dirEntry of dirEntries) {
        if (dirEntry.isFile()) {
            yield path.join(directory, dirEntry.name);
        } else if (dirEntry.isDirectory()) {
            yield* findAllFiles(path.join(directory, dirEntry.name));
        }
    }
}

for await (const file of findAllFiles("/")) {
    if (file.match(/that-file-i-was-looking-for/)) {
        console.log(`Found it!`);
        console.log(file);
        break;
    }
}

引用

是什么让这些比通过加载所有 进入数组并返回数组的 Promise,是 它们实际上并没有一次全部存储,所以如果列表非常 长(例如整个文件系统的情况)你只 实际上一次接收一个项目,内存使用量仅仅是 目录深度而不是文件数。

这种方法的另一个优点是,您无需处理您的 不需要,当在上述循环中使用 break 时,生成器 功能实际上只是停止。它不会继续超过最后一个文件 这是屈服的,因此我们不会搜索整个 如果我们尽早找到我们需要的文件系统。

---更新---

6 个月后,我对异步迭代有了更深入的了解。现在我看到使用for await...of 使用数据与异步生成器很好地分离,每个单独的都可以是一个简单的实现。而且我并不总是这两部分的作者。

顺便说一句,https://www.nodejsdesignpatterns.com/blog/javascript-async-iterators/ 提供了我读过的有关异步迭代器的最详细信息。

【讨论】:

    猜你喜欢
    • 2020-06-27
    • 2023-01-16
    • 1970-01-01
    • 2016-03-03
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多