了解Node.js事件循环.process.nextTick()从未被调用过.为什么?

cod*_*ent 10 events node.js

我正在试验事件循环.首先,我从这个简单的代码开始,读取并打印文件的内容:

var fs = require('fs');
var PATH = "./.gitignore";

fs.readFile(PATH,"utf-8",function(err,text){
    console.log("----read: "+text);
});
Run Code Online (Sandbox Code Playgroud)

然后我把它放到一个无限循环中.在这种情况下,永远不会执行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);
    });
}
Run Code Online (Sandbox Code Playgroud)

所以,我想做一些事情,以便为I/O调用分配与循环交织在一起的处理时间.我尝试使用process.nextTick()但它不起作用:

while(true){
    process.nextTick(function(){
        fs.readFile(PATH,"utf-8",function(err,text){
            console.log("----read: "+text)
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

为什么它不起作用,我怎么能做到?

Jay*_*uri 24

因为你的while循环仍在运行.它只是在下一个滴答中无限添加要​​做的事情.如果你放手,你的节点进程会因内存不足而崩溃.

当您使用异步代码时,您的正常循环和控制结构往往会让您失望.原因是它们在事件循环的一个步骤中同步执行.直到某些事情再次产生对事件循环的控制,没有任何'nextTick'会发生.

可以这样想,当你的代码运行时,你在事件循环的Pass B中.你打电话的时候

process.nextTick(function foo() { do.stuff(); })' 
Run Code Online (Sandbox Code Playgroud)

你要在开始传递事件循环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);
Run Code Online (Sandbox Code Playgroud)

(显然这是一个人为的例子,但你明白了)

这会导致每个"下一个文件"仅在完成前一个"nextTick"待办事项队列后才会被添加到"nextTick"待办事项队列中.

TL; DR:大多数时候,你不想在完成上一件事之前就开始做下一件事

希望有所帮助!