ES10 中异步迭代器的应用和使用技巧

JavaScript 是一门单线程、基于事件循环的语言,但是我们经常需要执行一些可能耗时较长的任务,如网络请求或者文件读写等。因此,语言中提供了异步编程的机制,即提供了异步函数和回调函数。

在 ES10 中,又增加了一种新的概念——异步迭代器,它的出现为异步编程带来了更好的体验和更高的效率。

什么是异步迭代器?

异步迭代器是一种可以通过 for await...of 语法进行迭代的对象。该语法可以遍历异步生成器函数中异步生成的值。异步生成器函数与普通的生成器函数类似,不同的是它可以异步生成值。

异步迭代器对象必须定义一个名为 [Symbol.asyncIterator] 的方法,该方法必须返回一个异步迭代器实例对象。异步迭代器实例对象必须定义一个名为 next 的方法,该方法返回一个 Promise 对象。如果异步迭代器已完成遍历,则必须返回一个 resolved Promise 并将 done 属性设置为 true。如果异步迭代器还没有完成遍历,则必须返回一个 Promise 并将 done 属性设置为 false。

如何使用异步迭代器?

我们可以通过 Promise 和 async/await 等常规的异步编程方法使用异步迭代器。以一个异步生成器为例,它可以生成一些数字并休眠一段随机时间:

async function* asyncGenerator() {
  let i = 0;
  while (i < 5) {
    // 休眠随机时间
    await new Promise(resolve => setTimeout(resolve, Math.random() * 1000));
    yield i++;
  }
}

现在我们可以使用 for await...of 语法遍历异步迭代器中的值:

(async () => {
  for await (const value of asyncGenerator()) {
    console.log(value);
  }
})();

在上述代码中,我们使用了 async/await 和 for await...of 语法来迭代异步生成器生成的值。

异步迭代器的应用场景和使用技巧

异步迭代器可以满足很多异步编程需求,可用于处理任何异步可迭代对象的数据。以下是一些常见的应用场景和使用技巧。

实现分页数据获取

异步迭代器可以用来实现分页数据获取。对于一些数据量很大的接口,在获取数据时,我们可以分页请求,分页请求的数据处理完毕后再发送下一页请求。

function getPage(page) {
  return fetch(`http://example.com/api?page=${page}`)
    .then(response => response.json())
    .then(data => ({
      done: data.length === 0,
      value: data
    }));
}

async function* paginationGenerator() {
   let page = 1;
   while (true) { // 确保异步生成器的无限循环
      const pageData = await getPage(page);
      if (pageData.done) {
         return;
      }
      yield pageData.value;
      page++;
   }
};

在上面的代码中,我们将分页请求的逻辑封装进异步生成器函数中,使用了无限循环来保证可以不断请求分页数据。当 done 属性为 true 时,异步生成器函数会结束。

我们可以使用 for await...of 语法来遍历异步生成器中的值:

(async () => {
   for await (const pageData of paginationGenerator()){
      // 处理分页数据
  }
})();

并行执行任务

异步迭代器不仅可以用于处理数据源,它还可以用于并行执行任务。使用异步迭代器并行执行任务时,我们要确保每个任务都是独立的,任务之间不会相互影响。

async function* doTask(tasks) {
  const taskPromises = tasks.map(task => Promise.resolve(task()));
  for (const promise of taskPromises) {
    yield Promise.resolve(promise);
  }
}

const tasks = [() => fetch('http://example1.com'), () => fetch('http://example2.com')];

(async () => {
  for await (const data of doTask(tasks)) {
      console.log(data);
  }
})();

在上面的代码中,我们传入了一个包含两个待执行任务的数组。使用异步迭代器并行执行这两个任务,从而提升了执行任务的效率。

总结

异步迭代器是 ES10 中新增的概念,它可以让我们更好地处理异步可迭代对象中的数据。异步迭代器不仅可以使用常规的异步编程方法处理异步可迭代对象的数据,还可以用于并行执行任务。例如,分页数据获取和并行任务执行。随着异步编程需求的增加,异步迭代器将会变得越来越重要。

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