ES10 中的 for await ...of 用法及例子

在 ES10 中,新增了一个非常有用的语法:for await ...of。这个语法可以让我们更方便地遍历异步迭代器,并且使得我们的代码更加简洁易读。在本文中,我们将深入介绍 for await ...of 的用法,并且提供一些实际的例子来帮助你更好地理解它。

异步迭代器

在介绍 for await ...of 之前,我们需要先了解一下异步迭代器。异步迭代器是一种特殊的迭代器,它可以遍历异步数据源并返回一个 Promise。异步迭代器的一个常见例子是数据库查询,因为查询结果通常需要异步获取。

异步迭代器的定义如下:

----- --------- ---------------- -
  ----- --
  ----- --
  ----- --
-

上面的代码定义了一个异步迭代器,它可以遍历三个数值:1、2 和 3。这个异步迭代器是一个生成器函数,它使用 asyncyield 关键字来定义。在生成器函数中,我们可以使用 await 关键字来等待异步操作的结果。

for await ...of 的用法

现在我们已经了解了异步迭代器的概念,接下来我们来看看 for await ...of 的用法。for await ...of 可以用于遍历异步迭代器,并且在每次迭代中等待 Promise 的解析。

for await ...of 的语法如下:

--- ----- ------ ---- -- -------------- -
  -- ---
-

其中,asyncIterable 是一个异步迭代器对象,item 是每次迭代返回的值。在每次迭代中,for await ...of 都会等待 Promise 的解析,然后将解析的结果赋给 item

下面是一个简单的例子,它使用 for await ...of 遍历一个异步迭代器:

----- --------- ---------------- -
  ----- -------------------
  ----- -------------------
  ----- -------------------
-

------ ---------- -
  --- ----- ------ ---- -- ----------------- -
    ------------------
  -
-----

上面的代码中,我们定义了一个异步迭代器 asyncGenerator(),它可以遍历三个 Promise 对象。然后我们使用 for await ...of 遍历这个异步迭代器,并在每次迭代中输出 Promise 的解析结果。

for await ...of 的例子

下面我们来看一些实际的例子,来帮助你更好地理解 for await ...of 的用法。

例子一:遍历文件行

假设我们有一个大文件,我们想要按行读取这个文件并进行处理。由于文件很大,我们不能一次性将整个文件读入内存,所以我们需要使用异步方式来读取文件。下面是一个使用 for await ...of 遍历文件行的例子:

----- -- - --------------

----- --------- ------------------- -
  ----- ---------- - ------------------------------
  ----- ------ - -----------------------

  --- - ------ ------ ----- ---------- - - ----- --------------
  --- ------- - --- --------------

  ----- ------------- -
    --- --- - --------------------- - ------- ---- ---
    --- ----- - ----------------

    --- ---- - - -- - - ------------ - -- ---- -
      ----- ---------
    -

    -- ------ ------ ----- ---------- - - ----- ---------------
  -

  -- ------- -
    --- --- - --------------------- - ------- ---- ---
    --- ----- - ----------------
    --- ---- - - -- - - ------------- ---- -
      ----- ---------
    -
  -
-

------ ---------- -
  --- ----- ------ ---- -- ---------------------------- -
    ------------------
  -
-----

上面的代码中,我们定义了一个异步迭代器 readLines(),它可以遍历一个文件的每一行。在 readLines() 函数中,我们使用 fs.createReadStream() 创建一个可读流,并使用 getReader() 方法获取一个可读流的读取器。然后我们使用 await 关键字等待读取器的 read() 方法返回一个 Promise,然后解析 Promise 的结果并将其赋给 chunkreaderDone 变量。

在每次迭代中,我们将 chunk 转换成字符串,并使用 \n 分隔符将其分割成多个行。然后我们使用 yield 关键字将每一行返回给调用方。在下一次迭代中,我们再次调用 read() 方法,直到整个文件都被读取完毕。

例子二:同时遍历多个异步迭代器

有时候我们需要同时遍历多个异步迭代器,并按照某种方式将它们合并起来。下面是一个使用 for await ...of 同时遍历多个异步迭代器的例子:

----- --------- ---------------------------------------- -
  ----- --------- - --------------------- -- ----------------------------

  ----- ------------------ -
    ----- - ------ ---- - - ----- ---------------------------- -- -----------

    -- ------ -
      ------------------------------------------ ---
    - ---- -
      ----- ------
    -
  -
-

----- --------- ----------------- -
  ----- -------------------
  ----- -------------------
  ----- -------------------
-

----- --------- ----------------- -
  ----- ---------------------
  ----- ---------------------
  ----- ---------------------
-

------ ---------- -
  --- ----- ------ ---- -- ---------------------------------------- ------------------- -
    ------------------
  -
-----

上面的代码中,我们定义了一个异步迭代器 combineAsyncIterators(),它可以同时遍历多个异步迭代器,并将它们合并成一个。在 combineAsyncIterators() 函数中,我们使用 map() 方法将每个异步迭代器转换成迭代器对象,并将这些对象存储在 iterators 数组中。然后我们使用 Promise.race() 方法等待所有迭代器中的下一个值,并返回最先解析的 Promise 的结果。如果某个迭代器已经完成了遍历,则我们将其从 iterators 数组中移除。

在下面的代码中,我们定义了两个异步迭代器 asyncGenerator1()asyncGenerator2(),它们分别可以遍历三个 Promise 对象。然后我们使用 combineAsyncIterators() 同时遍历这两个异步迭代器,并在每次迭代中输出 Promise 的解析结果。

总结

for await ...of 是一个非常有用的语法,它可以让我们更方便地遍历异步迭代器,并且使得我们的代码更加简洁易读。在本文中,我们介绍了异步迭代器的概念,然后深入介绍了 for await ...of 的用法,并提供了一些实际的例子来帮助你更好地理解它。如果你在开发异步代码时遇到了困难,不妨试试使用 for await ...of 语法来简化你的代码。

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