等待异步函数在Node.js中返回

Gol*_*den 5 javascript asynchronous event-loop synchronous node.js

假设我在Node.js中有一个异步函数,基本上是这样的:

var addAsync = function (first, second, callback) {
  setTimeout(function () {
    callback(null, first + second);
  }, 1 * 1000);
};
Run Code Online (Sandbox Code Playgroud)

现在我当然可以以异步方式调用此函数:

addAsync(23, 42, function (err, result) {
  console.log(result); // => 65
});
Run Code Online (Sandbox Code Playgroud)

我想知道的是你是否能以某种方式同步调用这个函数.为此,我想要一个包装函数sync,它基本上做了以下事情:

var sync = function (fn, params) {
  var res,
      finished = false;

  fn.call(null, params[0], params[1], function (err, result) {
    res = result;
    finished = true;
  });

  while (!finished) {}

  return res;
};
Run Code Online (Sandbox Code Playgroud)

然后,我可以addAsync通过这种方式调用它来同步运行:

var sum = sync(addAsync, [23, 42]);
Run Code Online (Sandbox Code Playgroud)

注意:当然你不会使用params[0]params[1]实际使用,但相应地使用arguments数组,但我想在这个例子中保持简单.

现在,问题是,上面的代码不起作用.它只是阻塞,因为while循环阻塞并且不释放事件循环.

我的问题是:是否有可能以任何方式使这个样本按预期运行?

我已经尝试过setImmediate以及process.nextTick其他各种各样的事情,但是他们没有帮助.基本上,您需要的是告诉Node.js请暂停当前函数,继续运行事件循环以及稍后返回的方法.

我知道你可以实现类似的使用yield和生成器函数,至少在Node.js 0.11.2及更高版本中.但是,我很好奇它是否有效甚至没有?

请注意,我完全了解如何在Node.js,事件循环和所有相关的东西中进行异步编程.我也充分意识到编写这样的代码是一个坏主意,尤其是在Node.js. 而且我也充分意识到"积极等待"也是一个愚蠢的想法.因此,请不要提供建议,以了解如何异步或类似的方式.我知道.

我问的原因只是出于好奇和想要学习.

Luc*_*ato 12

我最近创建了更简单的抽象WaitFor来在同步模式下调用异步函数(基于Fibers).它处于早期阶段但有效.请试试:https://github.com/luciotato/waitfor

使用WaitFor您的代码将是:

console.log ( wait.for ( addAsync,23,42 ) ) ;
Run Code Online (Sandbox Code Playgroud)

您可以调用任何标准nodejs异步函数,就像它是同步函数一样.

wait.for(fn,args ...)满足了与示例中"sync"函数相同的需求,但在光纤内部(没有阻塞节点的事件循环)


小智 1

  • 您可以使用 npm Fiber(C++ AddOn 项目)和节点同步
  • 在 C(++) 中实现阻塞调用并将其作为库提供

是的,我知道 - 你知道 - 但永远永远永远;)

非阻塞)使用控制流库