通过使用递归循环,您可以在完全不阻塞事件循环的情况下做到这一点。这样,您最终得到的只是每次调用在给定时间启动一个数据库工作者。假设您正在执行的数据库工作是异步的,那么您的代码并没有真正阻塞事件循环。但是 foo 循环仍然同时启动了一堆工作人员,这往往会阻塞事件循环(而不是阻塞它)。你是对的,它阻塞了事件循环,而你的 for 循环从 0 计数到数组的大小。以下内容完全相同,但您一次只启动一个数据库工作程序(好),并且您永远不会从 0 数到长度。在当前电子邮件的工作完成后,每个工作人员都会从列表中弹出,并且您的全局事件循环将留给处理其他事情,而不是 email_list。
var email_list = ['email1@email.com', 'email2@email.com', 'email100@email.com'];
function checkEmailList(emails, emailCallBack, completionCallback) {
var someDataCollectdOverAllEmails = '';
function checkEmailAsync(email) {
db.doSomeDBWorkAsync(email, function (data) {
someDataCollectdOverAllEmails += data;
if (email_list.length) {
checkEmail(email_list.pop()); //If there are still emails to be checked, check the next one ine line
} else {
completionCallback(someDataCollectdOverAllEmails);//IF not, call the completionCallBack
}
emailCallBack(data);
});
}
checkEmailAsync(emails.pop());
}
function logIndividualEmailData(data) {
console.log('Sningle Email: ' + data);
}
function logGlobalEmailData(data) {
console.log('All Email Data: ' + data);
}
checkEmailList(email_list, logIndividualEmailData, logGlobalEmailData);
Process.nextTick 示例
process.nextTick(function () {
'use strict';
console.log('printed second');
while (true);
});
process.nextTick(function () {
'use strict';
console.log('never printed');
});
console.log('printed first');
但是请注意,在下面的示例中,尽管 loopForever 将永远运行,它仍然允许读取我们的两个文件。如果我们只有 while(true) 它当然会阻止并且不允许这样做,并且我们的文件数据之一不会被打印出来。
var files = ['blah.js', 'file.js'];
for(var i = 0; i < files.length; i++) {
fs.readFile(files[i], function (err, data) {
console.log('File data' + data);
function loopForver(loop) {//asynchronously loop forever, pretty cool, but only useful for really specific situations!
process.nextTick(function () {
if(loop) {
console.log('looping');
loopForver(true);
}
});
}
loopForver(true);
});
}