如何在node.js中创建非阻塞异步函数?

Ric*_*ard 23 node.js

如何创建非阻塞异步函数?以下是我想要实现的,但我的程序仍在阻止......

var sys = require("sys");

function doSomething() {
  sys.puts("why does this block?");
  while(true);
}

setTimeout(doSomething,0);
setTimeout(doSomething,0);
setTimeout(doSomething,0);

sys.puts("main");
Run Code Online (Sandbox Code Playgroud)

s4y*_*s4y 34

Reddit交叉发布.


JavaScript中异步函数的用途与您所寻求的有点不同.

请记住,JavaScript是单线程的 - 它一次只能做一件事.这是一些传统的阻塞代码:

sys.puts("Before");
sleep(10);
sys.puts("After");
Run Code Online (Sandbox Code Playgroud)

在实际的Web应用程序中,sleep()may可能是一个耗时的数据库调用,网络请求(如等待来自用户Web浏览器的数据),帮助工具或文件访问.

如果您使用上述阻塞调用,Node.js服务器将无法在等待时执行任何其他操作(如开始处理其他Web请求).

PHP和许多其他Web编程环境通过为每个请求创建完全独立的线程来处理此问题.Node.js使用回调函数.您可以编写相同的代码,而不是:

sys.puts("Before");
setTimeout(function(){
    sys.puts("After");
}, 10000);
Run Code Online (Sandbox Code Playgroud)

在这里,您创建一个函数并将其传递给setTimeout().它的代码还没有运行,但是当它执行时,它将可以访问创建它的所有范围(所有变量).setTimeout()获取对该函数的引用,并在超时到期后调度事件循环中触发的事件.

事件循环本质上是Node.js程序的待办事项列表(它们很常见 - 计算机上运行的所有GUI应用程序可能都使用事件循环!).

调用之后setTimeout(),当前函数继续执行.它最终返回,并且调用它的函数返回,依此类推,直到程序在事件循环中结束.事件循环在代码执行时查看是否发生了任何事情(例如传入的请求),并在代码中调用相应的函数.如果不是,它会等待直到有没有发生(如超时到期).

异步代码不会让你的代码同时做很多事情,当某些代码依赖于外部的东西继续时,它确实消除了阻塞.

你很少需要在Node.js程序中进行阻塞工作.如果你这样做,你应该把这个工作分成一个单独的进程(甚至可以是另一个Node.js程序),或编写一个可以免费使用线程的C/C++插件.


npo*_*cop 17

您只能使用node.js运行时提供的异步IO函数或用C++编写的node.js扩展,在node.js中执行异步IO.您自己的Javascript代码在node.js中始终是同步的.很少需要异步非IO代码,node.js设计者决定完全避免使用它.

在node.js中异步运行Javascript有一些神秘的方法,其他评论者提到,但node.js并不是为这类工作而设计的.如果你需要这种类型的并发,请使用Erlang,node.js只是关于并行计算的IO,而对于并行计算,它与Python或PHP一样糟糕.


Fel*_*fer 10

您需要在单独的进程中运行阻塞功能.

该模块可以提供帮助:http://github.com/cramforce/node-worker

  • 重要的是要理解节点不是关于始终异步的函数.这是关于*i/o*是异步和非阻塞的.如果您的函数不执行任何i/o,则节点不会帮助您使其异步.它提供了允许您这样做的工具.像儿童过程一样.这就是费利克斯得到的答案.您的函数可以生成子进程来完成您的工作,它将执行主事件循环. (27认同)

b_e*_*erb 6

如果你不想使用 WebWorker API / node-worker,它仍然非常 alpha,只需创建一个额外的节点程序并通过 TCP 或 HTTP 进行通信。

这允许您将您的工作作为 HTTP 调用或原始 TCP 数据分派,并异步等待 HTTP 响应/传入 TCP 响应。

但是请注意,这仅适用于您的任务易于序列化的情况。


ken*_*ytm 4

setTimeout不会创建新线程,因此浏览器仍然会挂在无限循环上。

您需要重新考虑您的程序结构。