【问题标题】:Trying to understand generators / yield in node.js - what executes the asynchronous function?试图理解 node.js 中的 generators / yield - 什么执行异步函数?
【发布时间】:2013-07-05 05:07:43
【问题描述】:

Node.js 现在有生成器。

我的理解是,生成器可用于编写看起来更线性的代码,并避免回调地狱和末日风格编码的金字塔。

所以到目前为止,我的理解是在生成器内部,代码会一直执行,直到它到达“yield”语句。生成器函数的执行此时暂停。 yield 语句指定了一个可能是函数的返回值。通常这将是一个阻塞 I/O 函数 - 通常需要异步执行。

yield 的返回函数返回到任何称为生成器的地方。

我的问题是,此时会发生什么?究竟是什么执行了 yield 返回的阻塞 I/O 函数?

编写看起来是线性的生成器/收益代码是否正确,需要有一种特定类型的函数来调用生成器,一个循环通过生成器并执行收益返回的每个异步函数的函数并将异步函数的结果返回到生成器中?

我仍然不清楚 yield 返回的异步函数是如何执行的。如果是由调用生成器的函数执行的,是异步执行的吗?我猜是因为否则会导致阻塞行为。

总结一下我的问题:

  1. 要使用生成器编写“线性”异步代码,是否必须有一个调用函数来迭代生成器,将产生的函数作为回调执行并将回调的结果返回到生成器?
  2. 如果问题 1 的答案是肯定的,那么产生的函数究竟是如何执行的 - 异步?

谁能更好地概述/总结整个过程的工作原理?

【问题讨论】:

标签: node.js generator yield


【解决方案1】:

使用生成器编写异步代码时,您会处理两种类型的函数:

  • 普通函数用function 声明。这些函数不能产生。你不能以同步的方式编写异步代码,因为它们会运行到完成;您只能通过回调处理异步完成(除非您调用额外的功能,如 node-fibers 库或代码转换)。
  • generator 函数用function* 声明。这些函数可以产生。您可以在其中以同步样式编写异步代码,因为它们可以产生。但是您需要一个伴随函数来创建生成器、处理回调并在每次触发回调时使用next 调用来恢复生成器

有几个库实现了伴随函数。在大多数这些库中,伴随函数一次处理一个function*,您必须在代码中的每个function* 周围放置一个包装器。星系库(我写的)有点特别,因为它可以处理 function* 调用其他 function* 而无需中间包装器。伴随函数有点棘手,因为它必须处理一堆生成器。

由于yield/next 与您的 function* 和伴随函数之间的小舞蹈,执行流程可能难以理解。理解流程的一种方法是使用您选择的库编写一个示例,在您的代码和库中添加 console.log 语句,然后运行它。

【讨论】:

    【解决方案2】:

    如果[阻塞io函数]被调用的函数执行 生成器,它是异步执行的吗?我猜是因为 否则会导致阻塞行为。

    我认为生成器不会进行异步任务处理。对于生成器,只有一件事同时执行——只是一个函数可以停止执行并将控制权传递给另一个函数。例如,

    function iofunc1() {
      console.log('iofunc1');
    }
    
    function iofunc2() {
      console.log('iofunc2');
    }
    
    function* do_stuff() {
      yield iofunc1;
      yield iofunc2;
      console.log('goodbye');
    }
    
    
    var gen = do_stuff();
    (gen.next().value)(); 
    (gen.next().value)(); //This line won't begin execution until the function call on the previous line returns
    gen.next(); //continue executing do_stuff
    

    如果你读过一些关于 nodejs 生成器的文章:

    1. http://jlongster.com/2012/10/05/javascript-yield.html
    2. http://jlongster.com/A-Study-on-Solving-Callbacks-with-JavaScript-Generators
    3. http://jlongster.com/A-Closer-Look-at-Generators-Without-Promises

    ...它们都使用额外的函数/库来添加异步执行。

    【讨论】:

      【解决方案3】:

      1:用生成器编写“线性”异步代码,是否有必要 有一个迭代生成器的调用函数, 将产生的函数作为回调执行并返回结果 回调回生成器?

      是的。我们称它为“启动器”。

      2:如果问题 1 的答案是肯定的,那么究竟是如何产生的 函数执行 - 异步?

      在生成器中,您生成一个数组,其中包含:函数及其参数。在控制调用者(启动器)中,您使用 fn.apply(..,callback) 调用异步,将调用置于“generator.next(data);” (恢复)在回调中。

      异步函数异步执行,但生成器会在屈服点“暂停”,直到回调被调用(然后“generator.next(data)”被执行)

      完整的工作库和示例: https://github.com/luciotato/waitfor-es6

      【讨论】:

        猜你喜欢
        • 2014-06-26
        • 1970-01-01
        • 2023-04-04
        • 1970-01-01
        • 2013-02-02
        • 1970-01-01
        • 2016-06-11
        • 2021-03-29
        • 2015-09-29
        相关资源
        最近更新 更多