如何使用Node.js Fibers运行代码

我有一个关于Nodejs光纤的问题(这对我来说是绝对新的)…我有Nodejs光纤的这个教程, http: //bjouhier.wordpress.com/2012/03/11/fibers-and-threads-in- node-js-what-for / ,这里有一个例子

var fiber = Fiber.current; db.connect(function(err, conn) { if (err) return fiber.throwInto(err); fiber.run(conn); }); // Next line will yield until fiber.throwInto // or fiber.run are called var c = Fiber.yield(); // If fiber.throwInto was called we don't reach this point // because the previous line throws. // So we only get here if fiber.run was called and then // c receives the conn value. doSomething(c); // Problem solved! 

现在基于这个例子,我创build了我自己的代码版本,

  var Fiber = require('fibers'); function sample(callback){ callback("this callback"); } var fiber = Fiber.current; sample(function(string){ fiber.run(string); }); var string = Fiber.yield(); console.log(string); 

但是这给了我一个错误,

 /home/ubuntu/Tasks/ServerFilteringV1/test.js:28 fiber.run(string); ^ TypeError: Cannot call method 'run' of undefined 

而且我还有另外一个例子,它会在1000毫秒之后的callback函数里运行一个函数(我已经在callback函数之前用长时间的执行来testing函数了),

 var Fiber = require('fibers'); function forEach(callback){ setTimeout(function(){ callback("this callback"); },1000); } var fiber = Fiber.current; forEach(function(string){ fiber.run(string); }); var string = Fiber.yield(); console.log(string); 

这里的代码给了我另一个错误,

 /home/ubuntu/Tasks/ServerFilteringV1/test.js:30 var string = Fiber.yield(); ^ Error: yield() called with no fiber running 

那么,应该在run()函数执行之后等待yield()? 任何有关我的nodejs代码发生什么想法? 并提前感谢…

例1

光纤是一种轻量级的执行线程。 像真正的线程和进程一样,一个光纤必须被赋予一个代码块来在运行时执行。 你从bjouhier那里得到的代码是不行的。 这是打算在光纤内运行,就像这样:

 var f = Fiber(function() { var fiber = Fiber.current; sample(function(str) { fiber.run(string); }); var str = Fiber.yield(); console.log(str); }); f.run(); 

在光纤上run调用run的是光纤代码,这个代码是作为Fibercallback给出的。 上面的代码也会给出一个错误(说明光纤已经在运行)。 在分析执行顺序时,可以很容易地看到为什么。

  1. variablesf 设置为光纤。
  2. 运行光纤:
    1. 设置指向当前运行光纤的可变光纤。
    2. 调用函数sample
    3. 调用callback。
    4. 调用 fiber.run ,在当前光纤已经运行的情况下给出错误。

这个代码的结构是正确的,但是它假设sample是一些不立即调用callback的asynchronous函数。 我们用这个换掉你的sample函数:

 function sample(callback) { setTimeout(function() { callback("this callback"); }, 500); } 

现在,上面的代码不会发出错误,因为sample立即返回。 光纤内的执行顺序是:

  1. fiber指向当前正在运行的光纤。
  2. 调用 sample ,它将返回而不调用callback(还)。
  3. 调用 `Fiber.yield(),它暂停当前的光纤。
  4. 在500毫秒后, 调用callback。
  5. 调用 fiber.run()传递'this callback',它将恢复光纤。
  6. Fiber.yield返回, str 设置为“this callback”。
  7. 将stringlogging到控制台。

请注意,步骤4是在光纤执行之外完成的。

例2

而在第一个例子中,没有运行的光纤(因此fiber 未定义 ),在第二个例子中,由于相同的原因抛出错误。 同样,代码需要在光纤内运行。


产量和运行的function

光纤必须协同控制另一根光纤(或执行的主线)。 将它与线程和进程的优先性进行比​​较。 放弃控制是“ 屈服控制”的意思,在这种情况下,由Fiber.yield()

要继续执行(直接在光纤放置点之后),必须在光纤上调用run()

使价值进出纤维的机制是通过产量和运行的相互作用:

  • run的参数(在纤维之外)是由yield (在纤维内部)返回的。
  • yield (在纤维内部)的一个论据是由run (在纤维之外)返回的。

例如,查看github节点光纤存储库上的增量生成器。 此外,观察我们的例子1,给sample的callback基本上跑到了光纤外面 ,因为它在下一个刻度上运行(即setTimeout的asynchronous性质)。

正如Andrew所解释的那样,正如我在博客文章中所暗示的那样(请参阅下面的例子),您必须创build一个Fiber并使用run()运行它,以便能够调用Fiber.yield

当你有一个单独的asynchronous调用运行时,光纤的好处并不明显,但考虑一下你有一个调用f2调用f3的函数f1的情况。 如果f3使用callback调用低级别的asynchronous函数,并且如果不使用光纤,则必须将f3转换为具有callback的asynchronous函数,然后通过传染,还必须将f2f1变为asynchronous函数。 使用光纤,您可以将f1f2f3保留为正常function(无回叫)。 您需要在f3内部使用一些Fiber.yield()魔术,而且您还需要从Fiber内部调用f1 ,但是您不必担心f1f2的主体中的callback。

因此,当您的高级function与他们所调用的低级别asynchronousfunction之间有多层代码或复杂的控制stream程时,光纤会发光。

而且,编写纤维的Marcelbuild议您不要直接在代码中使用Fiber.yield() ,而是使用期货库。 用Fiber.yield来理解纤维是由什么材料制成的,但我鼓励你使用期货Fiber.yield一个真实的项目。 它也将帮助你并行化你的代码。