ECMAScript 2018( ES2018 ) 新功能 - 异步迭代

yufei       6 年, 4 月 前       1028

ECMAScript 2018( ES2018 ) 新功能 我们介绍了 TC39 会议已经票选出了 ES2018 的新功能

本着每一小节一个新功能的原则,本小节我们介绍另一个新功能,异步迭代

简介

使用 异步迭代 我们得到异步迭代器和异步迭代

异步迭代器跟常规的迭代器一样,除了除了它们的 next() 方法

异步迭代器 中的 next() 方法返回一个 {value,done} 对的 promise

为了使用异步迭代,我们需要在 for ...of 循环中使用 await 关键字

for await (const line of readLines(filePath)) {
  console.log(line);
}

JavaScript 中的异步迭代器

概述和愿景

ECMAScript 2015 中引入的迭代器接口是一种顺序数据访问协议,是一种通用的,用于组合数据消费者和变换器的开发方法

迭代器的主要方法是 next(),该方法返回一个 {value,done} 元组,其中 done 是一个布尔值,表示是否已到达迭代器的末尾,value 是序列中的生成值

因为迭代器的 next() 方法返回时必须知道序列中的下一个值和数据源的 「 完成 」状态,因此迭代器仅适用于呈现 同步 数据源

尽管我们 JavaScript 程序员遇到的许多数据源都是同步的 ( 例如内存列表和其他数据结构),但许多其他数据源却不同步。 例如,任何需要 I/O 访问的数据源通常使用基于事件或流的异步 API 来表示

遗憾的是,迭代器不能用于表示此类数据源

有人可能会说可以使用基于 promises 的迭代器,但这是远远不够的,因为 promises 只允许异步确定值,但却需要 同步 确定 「 完成 」 状态

为了为异步数据源提供通用数据访问协议,我们引入了 AsyncIterator 接口,异步迭代语句 ( for-await-of ) 和异步生成器函数

异步迭代器和异步迭代

异步迭代器很像普通的迭代器,除了它的 next() 返回 {value,done} 对的 promise

如上所述,异步迭代器的每个返回值都必须是 {value,done} 对的 promise,因为迭代器方法返回时迭代器的下一个值和 「 完成 」状态可能都是未知的

const { value, done } = syncIterator.next();
asyncIterator.next().then(({ value, done }) => /* ... */);

此外,该提案还引入了一个新符号 Symbol.asyncIterator ,用于从给定对象获取异步迭代器

这允许任意对象通告它们是异步迭代,就像 Symbol.iterator 允许我们将其作为普通的同步可迭代进行通告一样

使用 Symbol.asyncIterator 最明显的例子就是 可读流

异步迭代器的概念隐含了请求队列的概念。 由于在解决先前请求的结果之前可能会多次调用迭代器方法,因此每个方法调用必须在内部排队,直到所有先前的请求操作都已完成

异步迭代器语句 for-await-of

for-await-of 语句是该提案引入的 for-of 迭代语句的变体,它迭代异步可迭代对象

一般的用法如下

for await (const line of readLines(filePath)) {
    console.log(line);
}

注意 : 异步的 for-of 语句只允许在异步函数和异步生成器函数中使用

for-await-of 语句运行时,所需要的异步迭代器可以使用 [Symbol.asyncIterator]() 方法从数据源创建

而每次访问序列中的下一个值时,都会隐式使用 await 等待迭代器方法返回的 promise

异步生成器函数

异步生成器函数和普通的生成器函数相同,但有以下几点差别:

  1. 被调用时,异步生成器函数会返回一个对象,异步生成器的很多方法,比如 next()throwreturn 都会返回一个包含了 { value, done }promise,而不是直接返回 { value, done },这会自动使返回的异步生成器对象成为异步迭代器

  2. 异步生成器函数中可以使用 await 表达式和 for-await-of 语句

  3. 支持 yield * 委派给异步迭代

async function* readLines(path) {
  let file = await fileOpen(path);

  try {
    while (!file.EOF) {
      yield await file.readLine();
    }
  } finally {
    await file.close();
  }
}

这个函数返回一个异步生成器对象,该对象可以与 for-await-of 一起使用,就像上面代码中演示的那样

目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.