javascript - Node 纤维中的运行与产量之间有什么区别

标签 javascript node.js yield node-fibers

我找不到任何好的文档(或关于 SO 的任何问题)来解释 yieldrun 的工作原理。

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

例如(代码语法不正确),我怎样才能让这个函数同步返回response

  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 模式类中得到的一个对象(不确定它是否相关)。

提前致谢。

最佳答案

纤维不是新发明

Node fibers 可以通过在最底层以平台相关的方式保存当前执行环境的状态来暂停任何功能的运行(例如windows有一个fiber概念,没有广泛使用,比a更轻量级)线程,而不是抢占式)。

其他库使用语言特性模拟协程

所有其他的js库都是通过回调函数实现协程延续的,将执行状态保存在作用域变量中。这意味着您要么有回调金字塔、 promise 链,要么有异步/等待(我将装饰生成器与异步/等待放在同一个桶中)。

纤程也是协同例程的一种可能实现。纤程应该很快,将它们集成到您的代码中不需要您编写不同的代码风格或引入新的语法。可以根据您自己的代码随意更改的执行上下文(堆栈、寄存器等...)。

This cannot be done in pure JavaScript, node-fibers use native libraries to achieve this!

Node 纤程限制你,这样你就不会阻塞事件循环

node-fibers 的特定概念是:javascript 事件循环在所有纤程之外,因此您的初始代码也可以在没有纤程的情况下运行。如果您有一个 fiber 引用,您可以通过 fiber.run(); 将运行权限传递给它。当你在一个fiber内部时,你可以通过调用Fiber.yield();放弃运行权(有效的暂停当前运行的代码),javascript事件循环会继续。所有内置回调(setTimeoutPromise.then、事件处理程序、http 请求回调)都将在 javascript 事件循环中运行,无需纤程。

看这个例子

const Fiber = require("fibers");

function findDataAsync(param, callback) {
  setTimeout(() => {
    callback(null, "Async returned data");
  }, 100);
}

function findData( param ) {
  const currentFiber = Fiber.current;
  var response = null;

  findDataAsync(param, function (err, data) {
    response = { err : err, data : data };
    currentFiber.run();
  });
  Fiber.yield();
  if (response.err) {
    throw response.err;
  } else {
    return response.data;
  }
}


function main() {
  console.log("Inside fiber started");
  console.log(findData());
  console.log("Inside fiber finished");
}

console.log("Outside fiber started");
Fiber(main).run();
console.log("Outside fiber finished");

这应该输出:

Outside fiber started
Inside fiber started
Outside fiber finished
Async returned data
Inside fiber finished

请注意,Outside fiber finished 在调用 fiber 中的第一个 yield 后立即被记录。

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

关于javascript - Node 纤维中的运行与产量之间有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39703197/

相关文章:

javascript - 需要在屏幕调整大小时更改 div 输出和 javascript

node.js - 如何检测消息是否具有内联按钮电报机器人

python - `yield from` 生成器与 `yield from` 列表性能

ruby - 调用与 Gem 中的方法链接的参数时,yield block 的返回值是多少,用#each 迭代?

Javascript/Jquery - 从字符串中获取数字

javascript - React Native 多图像

javascript - JS浏览器加载动画

node.js - npm -v 与 npm list npm -g 不同

node.js - peer.on ('calll' ) 永远不会被调用

jquery - 将 <%=yield %> 放入 ajax jquery 调用的部分中