Javascript NextTick()不工作[将CPU密集型任务与其他事件交错]

Javascript NextTick()不工作[将CPU密集型任务与其他事件交错],javascript,node.js,Javascript,Node.js,我在看书 然而,它附带的代码并没有实现CPU密集型任务 我试着写我的版本。但这是错误的 执行compute()后,没有一个IO在服务 所以,我的问题是:在这种情况下,使用nextTick()函数的正确方法是什么 我不想在执行compute()时阻止IO var http = require('http'); function compute() { // performs complicated calculations continuously // ... var

我在看书 然而,它附带的代码并没有实现CPU密集型任务

我试着写我的版本。但这是错误的

执行compute()后,没有一个IO在服务

所以,我的问题是:在这种情况下,使用nextTick()函数的正确方法是什么

我不想在执行compute()时阻止IO

var http = require('http');

function compute() {

    // performs complicated calculations continuously
    // ...
    var result = 0;
    for(var i = 0; i < 1000000; i++){
        for(var j = i;  j < 1000000; j++){
            result += i + j;
        }
    }
    process.nextTick(compute);
}

http.createServer(function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World');
}).listen(5000, '127.0.0.1');


compute();
var http=require('http');
函数compute(){
//连续执行复杂的计算
// ...
var结果=0;
对于(变量i=0;i<1000000;i++){
对于(var j=i;j<1000000;j++){
结果+=i+j;
}
}
process.nextTick(compute);
}
http.createServer(函数(req,res){
res.writeHead(200,{'Content-Type':'text/plain'});
res.end(“你好,世界”);
}).听(5000,'127.0.0.1');
compute();

nextTick是一个阻塞调用(至少在节点v0.10.29中,我测试过这个),它阻止其他事件运行。使用setImmediate()

nextTick是一个阻塞调用(至少在节点v0.10.29中,我测试过这个),它阻止其他事件运行。使用setImmediate()。它没有赋予该函数神奇的非阻塞特性;JavaScript仍然是单线程的。如果函数阻塞(通过执行大量CPU限制的工作),它仍然会导致I/O事件排队,直到函数完成


如果您需要执行CPU密集型工作,.

nextTick
只需安排下一次调用您的函数。它没有赋予该函数神奇的非阻塞特性;JavaScript仍然是单线程的。如果函数阻塞(通过执行大量CPU限制的工作),它仍然会导致I/O事件排队,直到函数完成


如果您需要执行CPU密集型工作,.

setImmediate
将更好地工作,正如我在博客文章中所解释的,因为它将允许IO任务在再次锁定主执行线程以完全运行
计算之前运行。但正如其他答案所显示的那样,思考这一点的方式并不是“nextTick
不起作用”,而是“哎呀,我正试图在node.js应用程序中做一件你绝对不能做的事情,而且我得到了我被警告过的结果”。您不能在节点中占用执行线程,因为它是协作多任务。将计算分成小块,使用外部进程助手,将一些东西分割成支持的C++库等。

<代码>代码> SimTimeTea//Cube >将更好地工作在我的博客文章中,因为它允许IO任务再次运行,锁定主执行线程以运行完整的<代码>计算< /代码>。但正如其他答案所显示的那样,思考这一点的方式并不是“nextTick不起作用”,而是“哎呀,我正试图在node.js应用程序中做一件你绝对不能做的事情,而且我得到了我被警告过的结果”。您不能在节点中占用执行线程,因为它是协作多任务。将计算分成小块,使用外部进程助手,将一些东西分割成支持的C++库等。

我会重新编写代码。假设我们需要处理1000000个项目,并且有一个(cpu绑定,但有时可以调用)函数
computeItem()
和io绑定
positem()
。我们希望在后台处理尽可能多的项目,但仍然有响应事件循环。为简单起见,不使用外部工作人员/队列/服务。可能的解决办法:

var desiredLatency = 10; // ms

function doBackgroundWork() {
  var start = new Date();
  var end;
  var item; 
  while (item = computeItem()) {
    postItem(item);
    if (end - start >= desiredLatency) {
      setImmediate(doBackgroundWork); // resume at next event loop invocation after processing other handlers
    }
  }
}

http.createServer(function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World');
}).listen(5000, '127.0.0.1');
doBackgroundWork();

我会重写一下你的代码。假设我们需要处理1000000个项目,并且有一个(cpu绑定,但有时可以调用)函数
computeItem()
和io绑定
positem()
。我们希望在后台处理尽可能多的项目,但仍然有响应事件循环。为简单起见,不使用外部工作人员/队列/服务。可能的解决办法:

var desiredLatency = 10; // ms

function doBackgroundWork() {
  var start = new Date();
  var end;
  var item; 
  while (item = computeItem()) {
    postItem(item);
    if (end - start >= desiredLatency) {
      setImmediate(doBackgroundWork); // resume at next event loop invocation after processing other handlers
    }
  }
}

http.createServer(function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World');
}).listen(5000, '127.0.0.1');
doBackgroundWork();

nextTick
不阻塞。使用nextTick排队的函数绕过事件队列,并在当前运行的连续退出后立即运行。因此,如果它们像上面那样自递归,那么它们会阻止http服务器处理请求。这是另一回事
nextTick
本身不阻塞。它会安排一些东西“稍后”运行,控制权会立即传回代码。如果一个函数像OP的例子一样是CPU密集型的,那么何时精确地安排调用并不重要;它仍然可以防止在运行时触发I/O事件。不正确。阻塞调用和使事件循环饥饿的函数之间有一个微妙但重要的区别,尽管两者都不好。阻塞调用是一种在工作完成之前控制不会返回到调用用户代码的调用。另一方面,需要很长时间执行的函数将使事件循环饥饿(就像实际的阻塞调用一样),但不会直接由用户代码调用,因此不会阻止控制返回到用户函数的中间。说
nextTick
阻塞是不正确的,因为控件总是立即从它返回。
nextTick
setImmediate
setTimeout
之间的唯一区别是回调计划何时运行。分别在下一个滴答声开始时、当前事件队列结束时和将来某个时间。如果回调通过花费很长时间来执行工作而阻塞了事件循环,则称为使事件循环饥饿,因为它阻止了队列中的其他事件被调度。而且,它只阻塞JS线程。其他(本机)线程未被阻塞;它们将继续向队列中添加事件。
nextTick
不会阻塞。使用nextTick排队的函数将绕过事件队列,并在当前运行的可继续退出后立即运行。s