ES10 中的新特性:for await of 循环

在 ES10 中,引入了一个新的循环结构:for await of 循环。该循环结构可以用来循环异步迭代器(Async Iterable),这意味着我们可以很容易地遍历任何异步生成器(Async Generator)、异步迭代器对象(Async Iterator Object)或其他返回异步迭代器的类型。本文将详细介绍 for await of 循环的特性、使用场景以及示例代码。

for await of 循环的使用

在介绍 for await of 循环之前,我们首先来了解一下异步迭代器(Async Iterable),异步迭代器是一个实现了 Symbol.asyncIterator 方法的对象。这个方法返回一个异步迭代器对象(Async Iterator Object),它可以通过 for await of 循环来遍历。下面是一个异步迭代器的示例代码:

// 异步迭代器示例
const sleep = async (ms) => new Promise(resolve => setTimeout(resolve, ms))

const asyncIterable = {
  [Symbol.asyncIterator]: async function*() {
    let i = 0
    while (i < 5) {
      await sleep(1000)
      yield i++
    }
  }
}

// 使用 for await of 循环遍历异步迭代器对象
(async function() {
  for await (const num of asyncIterable) {
    console.log(num)
  }
})()

在上面的例子中,我们定义了一个异步迭代器 asyncIterable,它通过 Symbol.asyncIterator 方法返回一个异步迭代器对象。异步迭代器对象会提供一个 next 方法,我们可以通过调用该方法来遍历异步迭代器。而 for await of 循环可以直接帮我们完成这个任务,使得异步迭代器的遍历变得更加便利。需要注意的是,for await of 循环只能在异步函数内部使用(即 async/await 函数)。

for await of 循环的优势

for await of 循环的出现,使得我们能够更加方便地在异步函数内部遍历异步迭代器对象,不再需要手动写一个 while 循环调用 next 方法。这样可以让我们的代码更加简洁易懂。

同时,在异步场景下,可能会出现需要按顺序执行异步操作的情况。我们可以通过使用异步迭代器来表示这种操作,然后使用 for await of 循环来遍历异步迭代器对象,这样就能保证操作按顺序执行。

for await of 循环的示例代码

下面我们来看一些示例代码,更好地理解 for await of 循环的使用方法和优势。

示例 1:使用 for await of 循环遍历异步迭代器对象

// 异步迭代器示例
const sleep = async (ms) => new Promise(resolve => setTimeout(resolve, ms))

const asyncIterable = {
  [Symbol.asyncIterator]: async function*() {
    let i = 0
    while (i < 5) {
      await sleep(1000)
      yield i++
    }
  }
}

// 使用 for await of 循环遍历异步迭代器对象
(async function() {
  for await (const num of asyncIterable) {
    console.log(num)
  }
})()

示例 2:使用异步迭代器对象表示按顺序执行的异步操作

const http = require('http')

const urls = ['http://www.baidu.com', 'http://www.taobao.com', 'http://www.qq.com']

const fetch = async (url) => {
  const res = await new Promise((resolve, reject) => {
    http.get(url, (res) => resolve(res)).on('error', reject)
  })
  return new Promise(resolve => {
    let data = ''
    res.on('data', chunk => data += chunk)
    res.on('end', () => resolve(data))
  })
}

const asyncIterable = {
  [Symbol.asyncIterator]: async function*() {
    for (const url of urls) {
      const content = await fetch(url)
      yield content
    }
  }
}

// 使用 for await of 循环遍历异步迭代器对象,保证操作按顺序执行
(async function() {
  for await (const content of asyncIterable) {
    console.log(content)
  }
})()

在上面的例子中,我们使用一个异步迭代器对象来表示三个网站的内容,使用 for await of 循环来遍历这个异步迭代器对象,保证三个网站的内容会按顺序依次输出。

总结

在本文中,我们介绍了 ES10 中的新特性 for await of 循环。通过使用 for await of 循环,我们可以更加方便地遍历异步迭代器(Async Iterable),使得我们的代码变得更加简洁易懂。

同时,我们也给出了两个示例,展示了 for await of 循环的使用场景以及优势。如果你在异步编程中经常会使用到异步迭代器,那么 for await of 循环一定能帮到你。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b63077add4f0e0ffee11fa