试图理解node.js中的生成器/产量 - 什么执行异步函数?

时间:2013-07-07 22:17:38

标签: node.js generator yield

Node.js现在有了生成器。

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

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

yield的返回函数返回到所谓的生成器。

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

编写看似线性的生成器/良品代码是否正确,需要一个特定类型的函数来调用生成器,这个函数循环生成器并执行yield返回的每个asynch函数并将asynch函数的结果返回给生成器?

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

总结我的问题:

  1. 要用生成器编写“线性”异步代码,是否需要有一个遍历生成器的调用函数,将生成的函数作为回调执行并将回调结果返回给生成器?
  2. 如果问题1的答案是肯定的,那么生成的函数究竟是如何执行的 - 异步?
  3. 任何人都可以提供有关整个过程如何运作的更好的概述/摘要吗?

3 个答案:

答案 0 :(得分:11)

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

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

有几个库实现配套功能。在大多数这些库中,伴随函数一次只处理一个function*,并且必须在代码中的每个function*周围放置一个包装器。 Galaxy库(我写的)有点特殊,因为它可以处理function*调用其他function*而没有中间包装器。伴侣功能有点棘手,因为它必须处理一堆发生器。

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

答案 1 :(得分:4)

  

如果[阻塞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
  4. ...他们都使用额外的函数/库来添加异步执行。

答案 2 :(得分:2)

  

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

是。我们称之为“发射器”。

  

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

在生成器内部,您将生成一个数组:函数及其参数。在控制调用者(启动器)中,使用fn.apply(..,callback)来调用异步,将调用放到“generator.next(data);” (简历)在回调中。

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

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