Promise 黑科技 - Generator 异步流程控制方案

阅读时长 7 分钟读完

在 JavaScript 中,异步编程一直都是个难点。长久以来,回调函数是最常见的解决方案。而在 ES6 中,引入了 Promise,进一步改善了异步编程的体验。但是,即使在 Promise 出现之后,我们还是会遇到一些异步流程控制上的问题。这时,Generator 可以作为另一种黑科技般的解决方案。

1. Promise 的弊端

在探讨 Generator 处理异步流程控制的方案之前,我们需要先了解 Promise 的一些弊端。

1.1 嵌套问题

当你接连使用多个 Promise 的时候,你不可避免地会遇到嵌套的问题,这会形成所谓的回调地狱(callback hell)。

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

1.2 只能返回单个值

每个 Promise 只能 resolve/reject 一个值。如果你需要返回多个值,你只能将它们打包进一个数组或对象中,这可能会导致代码更加复杂。

2. Generator 的基础知识

Generator 是 ES6 新引入的一个黑科技。简单来说,它是一种能够暂停和恢复代码执行的函数。当你需要某些异步操作但是又希望代码执行到一个特定的点暂停的时候,Generator 可以充当一个类似于“协程”或者“轻量级线程”的角色。

2.1 声明 Generator 函数

Generator 函数可以使用 function* 来声明:

当你调用 Generator 函数时,它并不会马上执行,而是会返回一个迭代器对象,可以通过这个对象的 .next() 方法手动调用 Generator 函数。当遇到 yield 语句时,代码会暂停执行并将值返回给迭代器;当再次调用 .next() 方法时,代码会继续执行。

2.2 yield 关键字

yield 关键字是 Generator 函数的核心。它常常在异步操作中使用。当 Generator 函数执行到某个 yield 语句时,它会暂停执行并将值返回给迭代器。值可以通过 .next() 方法传递给 Generator 函数。

3. Generator 的异步处理方案

Generator 可以与 Promise 结合使用。通过 yield 关键字,代码可以在等待异步操作的同时继续运行。异步操作完成后,它们的值会被传递给下一个 yield 语句。

3.1 基础示例

下面是一个基础示例,展示了如何使用 Generator 控制异步操作。

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

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

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

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

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

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

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

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

3.2 wait 辅助函数

为了让 Generator 的代码更加整洁,可以编写一个名为 wait 的辅助函数来简化代码。wait 函数可以将 Promise 转换为 Generator 可以 yield 的值。

这个函数接收一个 Promise,然后使用 .then().catch() 方法包装它。它的返回值是一个数组,第一个元素代表错误(如果有的话),第二个元素是成功的返回值。

有了 wait 函数,generatorFunction 可以改写成这样:

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

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

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

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

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

4. Generator 的优势与局限性

4.1 优势

  • 可以简化异步流程控制的代码。
  • 可以返回多个值。
  • 更直接的错误处理(即使在异步操作过程中抛出错误也能捕获到并抛出)。

4.2 局限性

  • 需要编写额外的代码与 Promise 结合使用。
  • 代码可读性与可维护性都受到代码流的影响。

5. 总结

Promise 和 Generator 都是 JavaScript 中解决异步流程控制的强大工具。当 Promise 不足以胜任 Promise 的任务时,又想避免回调地狱的灾难性结局时,Generator 提供了一个相对简单的解决方案。记得加以利用!

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

纠错
反馈