Si vous êtes familier avec la programmation JavaScript côté client, vous avez peut-être utilisé les fonctions setTimeout et setInterval, qui permettent de retarder l'exécution d'une fonction pendant un certain temps. Par exemple, le code suivant, une fois chargé dans la page Web, ajoutera « Bonjour » au document de la page après 1 seconde :
setTimeout(function() {
document.write('
Bonjour.
');}, une Seconde);
Et setInterval permet à la fonction d'être exécutée à plusieurs reprises à des intervalles spécifiés. Si le code suivant est injecté dans une page Web, "Bonjour" sera ajouté au document de la page toutes les secondes :
setInterval(function() {
document.write('
Bonjour.
'); }, une seconde);
Le Web étant depuis longtemps devenu une plate-forme de création d'applications, plutôt que de simples pages statiques, de tels besoins émergent de plus en plus. Ces fonctions de planification de tâches aident les développeurs à mettre en œuvre une validation périodique des formulaires, une synchronisation retardée des données à distance ou des interactions d'interface utilisateur qui nécessitent des réponses retardées. Node implémente également pleinement ces méthodes. Côté serveur, vous pouvez les utiliser pour répéter ou retarder de nombreuses tâches, telles que l'expiration du cache, le nettoyage du pool de connexions, l'expiration de session, l'interrogation, etc.
Utilisez la fonction de retard setTimeout pour exécuter
setTimeout peut formuler un plan d'exécution pour exécuter la fonction spécifiée une fois dans le futur, tel que :
var timeout = setTimeout(function() {
console.log("timed out!");
}, timeout_ms);
Exactement identique au JavaScript côté client, setTimeout accepte deux paramètres. Le premier paramètre est la fonction qui doit être retardée et le deuxième paramètre est le temps de retard (en millisecondes).
setTimeout renvoie un handle de timeout, qui est un objet interne. Vous pouvez l'utiliser comme paramètre pour appeler clearTimeout pour annuler le timer. Sinon, ce handle n'a aucun effet.
Utilisez clearTimeout pour annuler le plan d'exécution
Une fois que vous avez obtenu le handle de délai d'attente, vous pouvez utiliser clearTimeout pour annuler le plan d'exécution de la fonction, comme ceci :
var timeout = setTimeout(function() {
console.log("timed out!");
}, timeoutTime);
clearTimeout(timeout);
Dans cet exemple, la minuterie ne sera jamais déclenchée et les mots « time out ! » ne seront jamais émis. Vous pouvez également annuler le plan d'exécution à tout moment dans le futur, comme dans l'exemple suivant :
Faire et annuler des plans d'exécution répétés pour les fonctions
setInterval est similaire à setTimeout, mais il exécutera une fonction à plusieurs reprises à des intervalles spécifiés. Vous pouvez l'utiliser pour déclencher périodiquement un programme afin d'effectuer des tâches telles que le nettoyage, la collecte, la journalisation, l'acquisition de données, l'interrogation, etc. qui doivent être effectuées à plusieurs reprises.Le code suivant affichera un « tick » sur la console toutes les secondes :
console.log("tick");
}, point final);
setInterval renvoie un handle de plan d'exécution, qui peut être utilisé comme paramètre de clearInterval pour annuler le plan d'exécution :
}, 1000);
// …
clearInterval(intervalle);
Utilisez process.nextTick pour retarder l'exécution de la fonction jusqu'au prochain tour de la boucle d'événements
Parfois, les programmeurs JavaScript côté client utilisent setTimeout(callback,0) pour retarder la tâche pendant une courte période. Le deuxième paramètre est de 0 milliseconde, ce qui indique au runtime JavaScript d'attendre immédiatement après que tous les événements en attente aient été traités. Exécutez cette fonction de rappel. Parfois, cette technique est utilisée pour retarder l’exécution d’opérations qui n’ont pas besoin d’être effectuées immédiatement. Par exemple, vous devez parfois commencer à lire une animation ou effectuer d'autres calculs après le traitement de l'événement utilisateur.
Dans Node, tout comme le sens littéral de « boucle d'événements », la boucle d'événements s'exécute dans une boucle qui traite la file d'attente d'événements. Chaque tour du processus de travail de la boucle d'événements est appelé un tick.
Vous pouvez appeler la fonction de rappel une fois à chaque fois que la boucle d'événements démarre le prochain tour (prochain tick) d'exécution. C'est exactement le principe de process.nextTick, et setTimeout et setTimeout utilisent la file d'attente d'exécution dans le runtime JavaScript, et Ne pas utiliser la boucle d'événements.
En utilisant process.nextTick(callback) au lieu de setTimeout(callback, 0), votre fonction de rappel sera exécutée immédiatement après le traitement de l'événement dans la file d'attente, ce qui est beaucoup plus rapide que la file d'attente d'expiration de JavaScript (en temps CPU pour mesurer ).
Vous pouvez retarder la fonction jusqu'au prochain tour de la boucle d'événement comme suit :
my_expensive_computation_function();
});
Remarque : L'objet processus est l'un des rares objets globaux de Node.
Bloquer la boucle d'événements
Le runtime de Node et JavaScript utilise une boucle d'événement à thread unique. Chaque fois qu'il boucle, le runtime traite l'événement suivant dans la file d'attente en appelant la fonction de rappel appropriée. Lorsque l'événement est exécuté, la boucle d'événements obtient le résultat de l'exécution et traite l'événement suivant, et ainsi de suite jusqu'à ce que la file d'attente des événements soit vide. Si l'exécution de l'une des fonctions de rappel prend beaucoup de temps, la boucle d'événements ne sera pas en mesure de gérer les autres événements en attente pendant ce temps, ce qui peut rendre l'application ou le service très lent.
Lors du traitement des événements, si des fonctions sensibles à la mémoire ou au processeur sont utilisées, la boucle d'événements deviendra lente et un grand nombre d'événements s'accumuleront, qui ne pourront pas être traités à temps, ni même bloquer la file d'attente.
Regardez l'exemple suivant de blocage de la boucle d'événements :
var a = 0;
while(true) {
un ;
}
});process.nextTick(function nextTick2() {
console.log("prochain tick");
});
setTimeout(fonction timeout() {
console.log("timeout");
}, 1000);
Lors de l'utilisation de setTimeout, les fonctions de rappel seront ajoutées à la file d'attente du plan d'exécution, et dans cet exemple, elles ne seront même pas ajoutées à la file d'attente. Il s'agit d'un exemple extrême, mais vous pouvez constater que l'exécution d'une tâche gourmande en processeur peut bloquer ou ralentir la boucle d'événements.
Quitter la boucle d'événements
En utilisant process.nextTick, vous pouvez différer l'exécution d'une tâche non critique au prochain tick de la boucle d'événements, ce qui libère la boucle d'événements afin qu'elle puisse continuer à exécuter d'autres événements en attente.Regardez l'exemple ci-dessous. Si vous envisagez de supprimer un fichier temporaire, mais que vous ne souhaitez pas que la fonction de rappel de l'événement de données attende cette opération IO, vous pouvez la retarder comme ceci :
process.nextTick(function() {
fs.unlink("/chemin/vers/fichier");
} );
});
Supposons que vous envisagez de concevoir une fonction appelée my_async_function, qui peut effectuer certaines opérations d'E/S (telles que l'analyse des fichiers journaux), et que vous avez l'intention de la laisser s'exécuter périodiquement. Vous pouvez utiliser setInterval pour l'implémenter comme ceci :
.setInterval(function() {
ma_async_function(function() {
console.log('ma_fonction_async terminée !');
} );
},intervalle);//Note du traducteur : le « ,intervalle » précédent a été ajouté par moi, l'auteur l'a peut-être omis en raison d'une erreur typographique
Note du traducteur : (Les parties en gras ci-dessous sont ajoutées par le traducteur et ne constituent pas le contenu du livre original)
Afin de faciliter la compréhension de cette partie du contenu, vous pouvez modifier le code de l'auteur pour qu'il puisse effectivement s'exécuter :
(fonction my_async_function(){
setTimeout(function(){
console.log("1");
},5 000 );
},intervalle);
Exécutez ce code et jetez un œil. Vous constaterez qu'après 5 secondes d'attente, "bonjour" est émis toutes les 1 seconde. Notre attente est qu'après l'exécution de la my_async_function actuelle (cela prend 5 secondes), attendez 1 seconde avant d'exécuter la prochaine my_async_function. Il devrait y avoir un intervalle de 6 secondes entre chaque sortie. Ce résultat est dû au fait que my_async_function n'est pas exécuté en série, mais que plusieurs s'exécutent en même temps.