5

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

var addAsync = function (first, second, callback) {
  setTimeout(function () {
    callback(null, first + second);
  }, 1 * 1000);
};

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

addAsync(23, 42, function (err, result) {
  console.log(result); // => 65
});

我想知道的是您是否可以以某种方式同步调用此函数。为此,我想要一个包装函数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;
};

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

var sum = sync(addAsync, [23, 42]);

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

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

我的问题是:是否有可能以任何方式使该示例按预期运行?

我已经尝试过setImmediateprocess.nextTick其他各种东西,但没有一个有帮助。基本上,您需要一种方法来告诉 Node.js 请暂停当前函数,继续运行事件循环,并在稍后的时间点返回。

我知道你可以实现类似的 usingyield和 generator 功能,至少在 Node.js 0.11.2 及更高版本中。但是,我很好奇即使没有它是否也有效?

请注意,我完全了解如何在 Node.js 中进行异步编程、事件循环和所有相关内容。我也完全意识到编写这样的代码是一个坏主意,尤其是在 Node.js 中。而且我也完全意识到“主动等待”也是一个愚蠢的想法。所以请不要建议学习如何异步执行或类似的操作。我知道。

我问的原因只是出于好奇和学习的愿望。

4

3 回答 3

12

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

使用 WaitFor 您的代码将是:

console.log ( wait.for ( addAsync,23,42 ) ) ;

你可以调用任何标准的 nodejs 异步函数,就好像它是一个同步函数一样。

wait.for(fn,args...)满足与示例中的“同步”功能相同的需求,但在 Fiber 内部(不阻塞节点的事件循环)

于 2013-08-12T07:23:59.453 回答
1
  • 您可以使用 npm 纤程(C++ AddOn 项目)和节点同步
  • 在 C(++) 中实现阻塞调用并将其作为库提供

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

Non-Blocking) 使用控制流库

于 2013-07-24T21:01:56.723 回答
0

标准的 Promises 和 yield(生成器函数)将使这个变得简单:

http://blog.alexmaccaw.com/how-yield-will-transform-node

http://jlong​​ster.com/A-Study-on-Solving-Callbacks-with-JavaScript-Generators

于 2014-11-11T08:49:30.413 回答