Node.js:如何在不阻塞事件循环的情况下重新创build“setTimeout”函数?

我做了大量的search,试图找出如何在Node.js中创build非阻塞代码。 不幸的是,我发现每个例子都是基于一个函数,最终已经有一个内置的callback函数。 所以我想用callback来创build自己的函数,但由于某种原因,它阻止了事件循环。 这没有阻止事件循环:

function foo(response){ setTimeout(function(){ response.writeHead(200, {"Content-Type": "text/plain"}); response.write("bar"); response.end(); }, 7000); } 

但是这样做了:

 function foo(response){ function wait(callback, delay){ var startTime = new Date().getTime(); while (new Date().getTime() < startTime + delay); callback(); } wait(function(){ response.writeHead(200, {"Content-Type": "text/plain"}); response.write("bar"); response.end(); }, 7000); } 

我错过了什么非阻塞代码的基本方面?

编辑:

我的目标是重新创buildsetTimeout更多的是一个心理练习,我想我会尝试,这样我可以更好地理解偶数循环。 现在我担心,如果我有一些相当沉重的服务器端代码,在JavaScript中做一些原始处理,我不知道如何阻止它停止我的事件循环。

在阅读你的答案之后,再思考一下,我认为一个更准确的问题可能是这样的:如果我正在使用JavaScript在服务器上进行繁重的处理,那么如何阻止中断事件循环呢?

这是我第一次在这里发表,所以我不知道我会得到什么样的回应。 到目前为止,这是真棒。 多谢你们。

编辑2:嘿,所以再次感谢大家的意见。 我结束了尝试process.nextTick像雷诺斯build议…它的工作! 我设法用callback创build了我自己的非阻塞计时器。 代码并不完美,但对于那些好奇的人来说,这是它的样子:

 var timer = {}; function delay(callback, length){ if(!timer.startTime){ timer.startTime = new Date().getTime(); timer.callback = callback; timer.length = length; } if(new Date().getTime() < timer.startTime + timer.length){ process.nextTick(delay); } else { timer.callback(); timer = {}; } } function list(response){ delay(function(){ console.log("callback"); exec("dir", function (error, stdout, stderr) { response.writeHead(200, {"Content-Type": "text/plain"}); response.write(stdout); response.end(); }); }, 7000); } 

不是真的打算使用这个代码。 但是学习如何做到这一点的过程肯定帮助我理解了一些关于非阻塞的关键概念。

对于那些仍然对非阻塞感到好奇的人,你应该检查一下Raynos的文章。

为了不阻塞事件循环,你的代码必须最终返回到事件循环,并允许它继续处理。 除非你的代码实际返回到事件循环,否则它不能出队下一个消息并处理它。 这段代码在给定的时间内不会退出,因此也不会将控制权返回给事件循环。

你有最正确的想法 – 你想写一个快速执行的函数,然后返回控制回到主事件循环。 而不是函数本身空闲等待(在你的情况下,通过字面上坐在一个while循环和睡眠),它注册一个callback – 通常与setTimeout – 然后返回。 然后,当超时被调用时,唤醒并执行它需要的任何function。

 function foo(response){ function wait(callback, delay){ var startTime = new Date().getTime(); // this will block the event loop until this condition is true while (new Date().getTime() < startTime + delay); //then the callback is called callback(); //then it goes back to the event loop } wait(function(){ response.writeHead(200, {"Content-Type": "text/plain"}); response.write("bar"); response.end(); }, 7000); } 

也许包装是你想要的?

 function wait(callback, delay){ setTimeout(callback, delay); } 

当你调用一个函数时,你不会启动一个新的线程。 因此,在等待函数中运行一个while循环会阻止执行。