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

Posted

技术标签:

【中文标题】在 Node.js 中等待异步函数返回【英文标题】:Wait for an async function to return in Node.js 【发布时间】:2013-07-24 13:05:03 【问题描述】:

假设,我在 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]params[1],而是相应地使用arguments 数组,但我想在这个例子中保持简单。

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

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

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

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

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

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

【问题讨论】:

并非如此。如果你在一段时间内“拿着麦克风”,它就不能执行回调。如果它不能执行回调它就不能设置 res。如果你在 while 上停下来让它可以执行回调,flow 会从外部函数中滑出,并且 res 在定义之前返回。可能有一个 NPM 工具可以编写这样的代码... 你是什么意思 可能有一个 NPM 工具来编写类似的代码 伪同步代码,看起来是程序化的,但在内部使用回调来执行您描述的逻辑。我自己用 throw 和 Function 完成了它,但这是一个讨厌的习惯。 你有这样的代码示例吗? github.com/0ctave/node-sync,davidwalsh.name/sync-exec,或者我所说的黑客:danml.com/pub/sentry.html 【参考方案1】:

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

使用 WaitFor 你的代码将是:

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

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

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

【讨论】:

【参考方案2】: 您可以使用 npm 纤程(C++ 插件项目)和节点同步 在 C(++) 中实现阻塞调用并将其作为库提供

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

非阻塞)使用控制流库

【讨论】:

:-))) ...问题是在某些情况下异步真的丑陋,并且阻塞调用的危害会小于另一个缩进级别。 npm node-ffi 可能是一个替代方案 - 但它也是一个 C(++) AddOn ;) @GoloRoden:如果您的异步“真的很丑”,请查看 IOC 和依赖注入来解开意大利面。异步可以像程序代码一样干净,没有嵌套回调。 当然有一些模式可以避免嵌套回调,但是 - 正如我的问题示例中所指出的 - 我想摆脱 any 回调,即使是第一个一。【参考方案3】:

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

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

http://jlongster.com/A-Study-on-Solving-Callbacks-with-javascript-Generators

【讨论】:

以上是关于在 Node.js 中等待异步函数返回的主要内容,如果未能解决你的问题,请参考以下文章

Node.JS - 无法使用try / catch块获得异步抛出

Node.js 回调函数

node js 回调函数

Node.js 回调函数

Node.js 回调函数

哪种方式更方便在无限循环中执行异步函数,每次执行之间都休眠(Node.js / Vanilla JS)