Javascript 节点光纤中的运行与产量有什么区别

Javascript 节点光纤中的运行与产量有什么区别,javascript,node.js,yield,node-fibers,Javascript,Node.js,Yield,Node Fibers,我找不到任何好的文档(或任何相关问题)来解释yield和run是如何工作的 我无法找到异步方法如何使用Fibers/futures返回值 例如(代码语法不正确),如何使此函数同步返回响应 function findData( param ) { var fiber = Fiber( function(){ var currentFiber = Fiber.current; Model.findOne({ "param" : param}, function

我找不到任何好的文档(或任何相关问题)来解释
yield
run
是如何工作的

我无法找到异步方法如何使用
Fibers/futures
返回值

例如(代码语法不正确),如何使此函数同步返回
响应

  function findData( param )
  {
    var fiber = Fiber( function(){
      var currentFiber = Fiber.current;
      Model.findOne({ "param" : param}, function (err, data) {
        response = { err : err, data : data };
      });
    });
    return fiber;
  }
差不多

  var value = findData("1");
这个
Model
是我从
Mongoose
schema类获得的对象(不确定它是否相关)

提前感谢。

纤维不是新发明 节点光纤通过以与平台相关的方式在最低级别保存当前执行环境的状态(例如,windows具有光纤概念,未广泛使用,比线程更轻,不可抢占),可以暂停任何功能的运行

其他库使用语言特性模拟协同例程 所有其他js库都通过使用回调函数实现共同例程延续,将执行状态存储在范围变量中。这意味着您要么拥有回调金字塔、承诺链,要么拥有async/await(我将修饰的生成器与async/await放在同一个存储桶中)

光纤也是co例程的一种可能实现。光纤应该是快速的,将它们集成到代码中不需要使用不同的代码样式,也不需要引入新的语法。执行上下文(堆栈、寄存器等),可以根据自己的代码随意更改

这不能在纯JavaScript中完成,节点光纤使用本机库来实现这一点

节点光纤会限制您,因此您不会阻止事件循环 特定于节点光纤的概念是:javascript事件循环位于所有光纤之外,因此初始代码也在没有光纤的情况下运行。如果您有光纤引用,可以通过
fiber.run()将运行权限传递给它。当您在光纤中时,可以通过调用
fiber.yield()放弃运行的权利(有效地挂起当前运行的代码),javascript事件循环将继续。所有内置回调(
setTimeout
Promise.then
,事件处理程序,http请求回调)都将在javascript事件循环中运行,无需光纤

看这个例子 这应该输出:

Outside fiber started
Inside fiber started
Outside fiber finished
Async returned data
Inside fiber finished
请注意,在调用光纤中的第一个成品后,会立即记录已完成的
外部光纤


如您所见,我们必须立即启动光纤,才能
产生
。如果尝试在第三方库中使用光纤,则必须确保库不会通过调用
setTimeout
或发出异步http请求将当前执行上下文“重置”到javascript事件循环中。

将函数更改为:

function findData(param) {
  var currentFiber = Fiber.current;
  Model.findOne({ "param" : param }, function(err, data) {
    if (err) fiber.throwInto(err);
    else fiber.run(data);
  });
  return Fiber.yield();
}
然后你可以写:

function doSomething() {
  var param = ...;
  var data = findData(param);
  processData(data);
}

function doLotsOfThings() {
  ...;
  doSomething();
  doSomethingElse();
}
等等,等等。。。您可以编写所有代码,就像
Model.findOne
是同步的一样

唯一的问题是不能直接从节点的事件循环调用这些函数中的任何一个。你必须在光纤中呼叫它们。通常,您将在HTTP侦听器(或TCP侦听器或其他)中创建光纤。典型代码:

http.createServer(function(request, response) {
  // you cannot call doLotsOfThings() here
  Fiber(function() {
    // but you can call it here
    try { doLotsOfThings(); }
    // and this the right place to catch exceptions too!
    catch (ex) { handleException(ex); }
  }).run();
}).listen(8124);
简言之,在调用异步函数时,您将在低级别调用
Fiber.yield
(上面的第一个模式),并在顶级侦听器中创建光纤(上面的第二个模式)。中间的所有代码都可以用同步样式编写


注意:使用这些代码模式,您不需要在每个函数中捕获/测试错误。相反,您可以使用经典的结构化异常处理(让异常冒泡起来)。

从我所看到的来看,
fibers
类似于或Bluebird,只是不太标准。我建议您看看这些模块(或者使用ES7)。在任何情况下,您都不能使异步代码与这些代码中的任何一个同步,它只是看起来更同步而已。@robertklep谢谢,将看一看谢谢详细的示例(+1),将试用您的代码。我试用了您的代码,
data
main
中返回,但如何在
Fiber()之外获取此数据
主事件循环中的构造函数?再次感谢。你不能,这就是重点。您必须在光纤中运行代码。为什么不包装一下程序的入口点呢?谢谢你的例子,我将试用你的代码+1Bruno,在第一个示例中,您在哪里使用光纤构造器?这些示例不是单独的;他们一起去。两种模式都需要。光纤构造器处于第二种模式。
http.createServer(function(request, response) {
  // you cannot call doLotsOfThings() here
  Fiber(function() {
    // but you can call it here
    try { doLotsOfThings(); }
    // and this the right place to catch exceptions too!
    catch (ex) { handleException(ex); }
  }).run();
}).listen(8124);