【问题标题】:How do I write non-blocking code in Node.js?如何在 Node.js 中编写非阻塞代码?
【发布时间】:2011-08-05 22:12:57
【问题描述】:

我可以很容易地在Node.js 中编写非阻塞I/O。这就是整个图书馆的目的。

但是任何完成的计算都是阻塞的。任何通过event emitters are blocking 的消息。

例如,发射事件会立即解决,因此是阻塞的:

var e = new process.EventEmitter;
e.on("foo", function() {
    console.log("event");
});
process.nextTick(function() {
    console.log("next tick");
});
setTimeout(function() {
    console.log("timeout");
}, 0);
e.emit("foo");

> event
> next tick
> timeout

除了在nextTick 中封装调用,我如何使代码非阻塞?

我希望在事件循环的每个周期中尽可能少地进行计算,以便我可以同时为尽可能多的客户端提供服务。

如何以非阻塞方式编写代码?

当我有非阻塞代码时,如何跨多个进程扩展它?

一个选项是等待 WebWorker 子流程 API 完成。

【问题讨论】:

  • 首先,90% 的“问题”实际上不是问题,更多的是节点事件库的问题,这应该作为功能请求或 github 上的可能错误提出,至于你的小问题,我会创建一个专门针对该主题的问题,而不是在这个问题中挤压它。
  • @RobertPitt 感谢您指出问题措辞不当。我已经调整过了。我也可能会在 github 上提到它。
  • 好一点,谢谢。

标签: javascript node.js blocking eventemitter


【解决方案1】:

在 JavaScript 中没有真正的多线程,这就是使调用非阻塞所需要的。我唯一能想到的就是网络工作者:https://developer.mozilla.org/en/Using_web_workers

【讨论】:

  • 再说一次,我已经好几年没用 JS 编程了,所以我可能错了。
  • process.nextTick 上的回调是非阻塞的。您可以使用事件循环来编写非阻塞代码,但事件发射器不使用事件循环。我不知道如何利用事件循环。
【解决方案2】:

JavaScript 是单线程的。这意味着,无论事件、超时或 nextTick 延迟如何,任何完成的计算都会阻塞整个过程。

如果您使用 process.nextTick 分步处理您的处理,就像在客户端使用 setTimeout(fn, 0) 完成以避免阻塞 UI 一样,您可以将工作量分散到更长的时间跨度上,为其他功能留出一些空间运行。

但这是一个非常无效的解决方案 - 工作总量是相同的,分布在所有周期中(使每个请求慢一点)。在实践中,任何预计花费超过几毫秒的计算都应该卸载到不同的进程。为了最大限度地提高并发性,您应该始终尽快返回事件循环

child_process.fork() 几天前被添加到 v0.5 中。它简化了子进程的创建和通信——不完全是网络工作者 API,但很接近,请参阅 URL https://github.com/joyent/node/blob/master/doc/api/child_process.markdown.

【讨论】:

  • 这正是我在 sn-p 中展示的内容。事件处理是阻塞的。我的问题是如何进行非阻塞消息传递以优化并发性?我想调用 process.nextTick 是最好的方法。
  • @RicardoTomasi 使用process.nextTick 是非阻塞的,因为它允许其他任务获得 CPU 时间。基本上是时间拼接一个 CPU 使其成为多线程。
  • Javascript 仍然是单线程的,你的函数会“阻塞”,不管它们的位置如何。 其他任务也会被阻塞,你只是切换它们的顺序。 如果您将处理分步进行,例如在客户端完成以避免阻塞 UI,您可以将相同数量的工作分散到更长的时间 - 那么您可能会获得更好的并发性,但是以换取更长的响应时间。这不是 node.js 的意义所在。非阻塞代码的好处来自于不等待响应,而不是避免所有计算。
  • @RicardoTomasi 最后的评论真的总结了我的误解。如果您可以编辑答案以解释我的误解,我会接受它
  • @Raynos 已编辑。还提到了新的.fork() API,你应该看看它。
猜你喜欢
  • 1970-01-01
  • 2015-05-15
  • 1970-01-01
  • 2011-09-13
  • 1970-01-01
  • 1970-01-01
  • 2019-05-21
相关资源
最近更新 更多