node.js:while 循环回调未按预期工作
Posted
技术标签:
【中文标题】node.js:while 循环回调未按预期工作【英文标题】:node.js: while loop callback not working as expected 【发布时间】:2012-10-03 20:15:08 【问题描述】:知道 Node.js 是异步工作时,编写如下代码:
function sleep()
var stop = new Date().getTime();
while(new Date().getTime < stop + 15000)
;
sleep();
console.log("done");
...会调用 sleep(),在 while 循环期间(15 秒)阻塞服务器,然后将“完成”打印到控制台。据我了解,这是因为 Node.js 只允许 javascript 访问主线程,因此这件事会停止进一步的执行。
所以我知道解决方案是使用回调:
function sleep(callback)
var stop = new Date().getTime();
while(new Date().getTime() < stop + 15000)
;
callback();
sleep(function()
console.log("done sleeping");
);
console.log("DONE");
所以我认为这会在 15 秒后打印“完成”。 '完成睡眠',因为 sleep() 函数被调用并被传递一个指向回调函数的指针。当这个函数工作时(while 循环),最后一行将被执行(打印 'done')。 15 秒后,当 sleep() 函数完成时,它会调用给定的回调函数,然后打印“完成睡眠”。
显然我在这里理解了一些错误,因为上述两种方式都阻塞了。有人可以澄清一下吗?
提前致谢, 斯拉格约科
【问题讨论】:
【参考方案1】:Javascript 和 node.js 是单线程的,这意味着一个简单的while
块;在while
块完成之前,不能处理任何请求/事件。回调并不能神奇地解决这个问题,它们只是帮助将自定义代码传递给函数。相反,使用process.nextTick
进行迭代,这将为您提供基本相同的结果,但也为要处理的请求和事件留出了空间,即它不会阻塞:
function doSleep(callback)
var stop = new Date().getTime();
process.nextTick(function()
if(new Date().getTime() < stop + 15000)
//Done, run callback
if(typeof callback == "function")
callback();
else
//Not done, keep looping
process.nextTick(arguments.callee);
);
doSleep(function()
console.log("done sleeping");
console.log("DONE");
);
【讨论】:
你把自己弄复杂了。一个简单的 setTimeout(callback, delay) 应该足以产生与异步指示相同的内容。 @FabiánH.jr.关键是 OP 可能有兴趣了解为什么他的while
不起作用以及如何以非阻塞方式编写while
,恕我直言,这比“你的方法无关紧要”更好不行,换个方法吧”。
好吧,总体来说很好的答案,现在你提到它,它在 node.js 的内部过程中非常有见地
有趣的是,我知道单独的 while 循环会阻止脚本执行其他操作,因为它正在在一个线程中运行。出于某种原因,我认为节点会识别阻塞代码,如果我用回调调用它,它只会让它工作并在完成后返回它,同时执行最后一行。当然,这是无意义的,因为只有一个线程可以工作,而且由于节点当然 not '看到'有一个繁忙的循环,它不会移动这个函数进入一个单独的线程,因此主线程被阻塞。
因此 process.nextTick 在事件循环的下一个滴答声中逐字执行给定的函数,让其他排队的任务,例如应该打印“完成”的最后一行,在脚本停止之前执行15 秒循环的下一个刻度。因此,假设我们将循环 5 毫秒,并且在该循环之外还有 5 个其他任务要完成,我猜使用 process.nextTick 将执行排队的任务 #1,然后执行 5 毫秒循环的一个滴答声,然后是任务 #2,依此类推对吧?【参考方案2】:
您立即调用sleep
,新的sleep
功能块。它不断迭代,直到满足条件。你应该使用setTimeout()
来避免阻塞:
setTimeout(function ()
console.log('done sleeping');
, 15000);
【讨论】:
【参考方案3】:回调与异步不同,它们只是在您想从异步操作中获取...回调时很有帮助。在您的情况下,该方法仍然同步执行; Node 不只是神奇地检测到有回调和长时间运行的操作,并使其提前返回。
真正的解决方案是使用setTimeout
,而不是另一个线程上的繁忙循环。
【讨论】:
【参考方案4】:如前所述,异步执行应该通过 setTimeout() 而不是 while 来实现,因为 while 会冻结在一个“执行帧”中。
您的示例中似乎还有语法错误。
这个很好用:http://jsfiddle.net/6TP76/
【讨论】:
以上是关于node.js:while 循环回调未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章
Node.js express.json 中间件未按预期解析请求