generator

让一个对象支持for...of遍历

  • 方法一

const range = {
  from: 0,
  to: 10,

  [Symbol.iterator]() {
    return { // 第一次会使用current的值
      current: this.from,
      last: this.to,

      next() { // 后续每次for...of都会调用next(),当done为true时候结束调用
        if (this.current <= this.last) {
          return {
            done: false,
            value: this.current++
          }
        }
        return {
          done: true
        }
      }
    }
  }
}


console.log([...range]) // (11) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • 方法二

Async Iterator

为了使对象可以异步迭代:

  1. 我们需要使用 Symbol.asyncIterator 取代 Symbol.iterator

  2. next() 方法应该返回一个 promise

  3. 我们应该使用 for await (let item of iterable) 循环来迭代这样的对象

正如我们所看到的,其结构与常规的 iterator 类似:

  1. 为了使一个对象可以异步迭代,它必须具有方法 Symbol.asyncIterator (1)

  2. 这个方法必须返回一个带有 next() 方法的对象,next() 方法会返回一个 promise (2)

  3. 这个 next() 方法可以不是 async 的,它可以是一个返回值是一个 promise 的常规的方法,但是使用 async 关键字可以允许我们在方法内部使用 await,所以会更加方便。这里我们只是用于延迟 1 秒的操作 (3)

  4. 我们使用 for await(let value of range) (4) 来进行迭代,也就是在 for 后面添加 await。它会调用一次 range[Symbol.asyncIterator]() 方法一次,然后调用它的 next() 方法获取值。

Iterator

Async Iterator

提供 iterator 的对象方法

Symbol.iterator

Symbol.asyncIterator

next() 返回的值是

任意值

Promise

要进行循环,使用

for..of

for await..of

Spread 语法 ... 无法异步工作

需要常规的同步 iterator 的功能,无法与异步 iterator 一起使用。

例如,spread 语法无法工作:

这很正常,因为它期望找到 Symbol.iterator,跟 for..of 没有 await 一样。并非 Symbol.asyncIterator

Async generator

Async Iterator

总结

常规的 iterator 和 generator 可以很好地处理那些不需要花费时间来生成的的数据。

当我们期望异步地,有延迟地获取数据时,可以使用它们的 async counterpart,并且使用 for await..of 替代 for..of

Async iterator 与常规 iterator 在语法上的区别:

Iterable

Async Iterable

提供 iterator 的对象方法

Symbol.iterator

Symbol.asyncIterator

next() 返回的值是

{value:…, done: true/false}

resolve 成 {value:…, done: true/false}Promise

Async generator 与常规 generator 在语法上的区别:

Generator

Async generator

声明方式

function*

async function*

next() 返回的值是

{value:…, done: true/false}

resolve 成 {value:…, done: true/false}Promise

在 Web 开发中,我们经常会遇到数据流,它们分段流动(flows chunk-by-chunk)。例如,下载或上传大文件。

我们可以使用 async generator 来处理此类数据。值得注意的是,在一些环境,例如浏览器环境下,还有另一个被称为 Streams 的 API,它提供了特殊的接口来处理此类数据流,转换数据并将数据从一个数据流传递到另一个数据流(例如,从一个地方下载并立即发送到其他地方)。

Last updated

Was this helpful?