ECMAScript 2019 中的 Generator 函数:使用手册

阅读时长 7 分钟读完

Generator 函数是一种特殊的函数,在 ECMAScript 2015 中被引入。这种函数不像普通函数一样运行到底就返回,而是可以暂停执行,并且可以根据需要再次开始执行。在 ECMAScript 2019 中,Generator 函数有了更多的特性和用法,本文将详细介绍如何使用它们。

基本语法和工作原理

定义 Generator 函数的语法非常简单,就是在函数关键字 function 后面加上一个星号。

调用 Generator 函数并不会立即执行函数体内的代码,而是返回一个指向内部状态的迭代器对象,也就是说函数内部的代码只有在迭代器的 next() 方法被调用时才会执行。

在第一次调用 next() 方法时,Generator 函数内部的代码会运行到第一个 yield 语句处,然后将 yield 后面的值返回给 next() 方法,并将函数运行状态作为 done 属性一起返回。再次调用 next() 方法时,函数将从上次停下的位置继续执行,直到运行完所有代码或者遇到下一个 yield 语句为止。

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

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

在最后一次调用 next() 方法时,Generator 函数返回的值是 { value: undefined, done: true },也就是说函数已经运行到底部并且没有再返回任何值了。

使用 yield*

在 Generator 函数中,yield 后面可以调用其他的 Generator 函数,这种语法被称作 yield*。使用 yield* 关键字时,Generator 函数会暂停自己并且执行被调用的 Generator 函数,待调用的函数运行结束后,控制权回到原始的 Generator 函数中,以便将结果值返回给调用者。

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

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

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

在这个例子中,当 generator1() 函数执行到 yield* generator2() 的时候,它会暂停执行,然后开始运行 generator2() 函数。当 generator2() 函数执行完毕之后,控制权回到 generator1() 函数中,并且从上次暂停的位置继续运行。

使用参数和返回值

Generator 函数可以接受参数并且返回值,这些特性都很容易使用。

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

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

在这个例子中,当我们调用 generator(1) 时,我们将 1 作为参数传递给了 Generator 函数。当我们第一次调用 next() 方法时,代码运行到 yield value + 1 处,将 2 作为 value 变量的值返回,此时控制权返回给调用者,我们可以将任何值通过第二次调用 next() 方法的参数传递给 result 变量,在这个例子中我们传递了 2。最后一次调用 next() 方法将代码运行到结尾并且返回 { value: undefined, done: true }

实战应用:生成器函数与 Promise

在实际应用中,Generator 函数可以非常方便地与 Promise 结合使用,以实现异步任务的序列化执行。

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

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

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

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

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

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

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

在这个例子中,我们定义了一个 fetchData() 函数,它返回一个 Promise 对象,在一秒钟后解析为一个字符串。然后我们定义了一个 generator() 函数,它使用 yield 语句依次调用两次 fetchData() 函数,并且在每次调用时打印返回的数据。最后我们定义了一个 runGenerator() 函数,它将执行 generator() 函数,然后在每次执行 fetchData() 函数时使用 Promise 对象传递数据和控制权,以便实现异步任务的序列化执行。

总结

Generator 函数是一种强大的函数,可以让我们使用类似于普通的同步代码的方式编写异步任务。本文介绍了 Generator 函数的基本语法和工作原理,以及如何使用 yield*、参数和返回值。最后我们还通过一个实际应用案例展示了如何将 Generator 函数与 Promise 结合使用。如果你想进一步学习 Generator 函数的使用,可以参考 MDN 的文档。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64852ade48841e9894414eb8

纠错
反馈