我正在尝试事件循环。首先,我从这个简单的代码开始,读取并打印文件的内容:
var fs = require('fs');
var PATH = "./.gitignore";
fs.readFile(PATH,"utf-8",function(err,text){
console.log("----read: "+text);
});
然后我把它放到一个无限循环中。在这种情况下,永远不会执行readFile函数。如果我没有弄错的话,因为Node的单线程忙于迭代而不会让I / O调用被执行。
while(true){
var fs = require('fs');
var PATH = "./.gitignore";
fs.readFile(PATH,"utf-8",function(err,text){
console.log("----read: "+text);
});
}
所以,我想做一些事情,以便为I / O调用分配与循环交织在一起的处理时间。我尝试使用process.nextTick()但它没有工作:
while(true){
process.nextTick(function(){
fs.readFile(PATH,"utf-8",function(err,text){
console.log("----read: "+text)
});
});
}
为什么它不起作用,我怎么能做到?
答案 0 :(得分:24)
因为你的while循环仍在运行。它只是在下一个滴答中无限添加要做的事情。如果你放手,你的节点进程会因内存不足而崩溃。
使用异步代码时,正常的循环和控制结构往往会让你失望。原因是它们在事件循环的一个步骤中同步执行。直到某些事情再次产生对事件循环的控制,没有任何'nextTick'会发生。
可以这样想,当你的代码运行时,你在事件循环的Pass B中。当你打电话
process.nextTick(function foo() { do.stuff(); })'
在开始传递事件循环C之前,你要将foo添加到'要做的事情列表'中。每次调用nextTick时,都会向列表添加一个,但在同步代码完成之前,它们都不会运行。
您需要做的是在回调中创建“做下一件事”链接。想想链接列表。
// var files = your list of files;
function do_read(count) {
var next = count+1;
fs.readFile(files[count], "utf-8", function(err,text) {
console.log("----read: " + text);
if (next < files.length) {
// this doesn't run until the previous readFile completes.
process.nextTick(function() { do_read(next) });
}
});
}
// kick off the first one:
do_read(files[0], 0);
(显然这是一个人为的例子,但你明白了)
这会导致每个“下一个文件”仅在完成前一个“nextTick”待办事项队列后才会被添加到“nextTick”待办事项队列中。
TL; DR:大部分时间,在上一件事完成之前,你不想开始做下一件事
希望有所帮助!