Vous pouvez le faire sans bloquer la boucle d'événement, en utilisant une boucle récursive. De cette façon, ce que vous finissez avec lance seulement un travailleur de base de données par appel, à un moment donné. En supposant que le travail de base de données que vous faisiez était asynchrone, votre code n'a pas vraiment bloqué la boucle d'événement. Mais la boucle du foor a encore lancé un tas de travailleurs simultanément, ce qui tendra à obstruer la boucle d'événement (pas le bloquer). Et vous avez raison de dire qu'il bloque la boucle d'événements pendant que votre boucle for compte à partir de 0, quelle que soit la taille de votre tableau. Ce qui suit fait exactement la même chose, mais vous ne lancez qu'un seul employé de base de données à la fois (bien), et vous ne comptez jamais de 0 à la longueur. Chaque travailleur est retiré de la liste après que le travail sur l'e-mail actuel est terminé, et votre boucle d'événements globale est laissée à traiter d'autres choses, pas les demandes de base de données email_list.length simultanément.
var email_list = ['[email protected]', '[email protected]', '[email protected]'];
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 exemple
process.nextTick(function() {
'use strict';
console.log('printed second');
while (true);
});
process.nextTick(function() {
'use strict';
console.log('never printed');
});
console.log('printed first');
Notez cependant que dans l'exemple ci-dessous, en dépit du fait que loopForever fonctionnera toujours, il permet encore nos deux fichiers à être lus. Si nous avions juste eu (vrai), cela bloquerait et ne permettrait pas cela et l'un de nos fichiers ne serait pas imprimé.
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);
});
}
Ce code ne bloque pas nécessairement. Vous devez boucler toutes les adresses e-mail et appeler les fonctions pour faire le travail de db, ceci est bien sûr bloquant. Mais si le travail DB est ASYNC, il ne bloquera que pendant la durée nécessaire pour compter 0 à email_list.length. Cela étant dit, vous pourriez envisager un modèle récursif, de sorte que vous n'avez même pas à attendre cela. – ChrisCM