Si vous connaissez la programmation JavaScript côté client, vous pouvez avoir utilisé les fonctions SetTimeout et SetInterval, qui permettent des retards pendant une période avant d'exécuter la fonction. Par exemple, le code suivant, une fois chargé sur la page Web, après 1 seconde, "Bonjour" sera ajouté après le document de la page:
La copie de code est la suivante:
var onesecond = 1000 * 1; // une seconde = 1000 x 1 ms
setTimeout (function () {
document.write ('<p> Bonjour. </p>');
}, OneSecond);
et SetInterval permet une exécution répétée des fonctions à des intervalles de temps spécifiés. Si le code suivant est injecté dans la page Web, il entraînera l'ajout de la phrase suivante "bonjour" au document de la page à chaque seconde:
La copie de code est la suivante:
var onesecond = 1000 * 1; // une seconde = 1000 x 1 ms
setInterval (function () {
document.write ('<p> Bonjour. </p>');
}, OneSecond);
Parce que le Web est devenu depuis longtemps une plate-forme pour créer des applications, plutôt qu'une simple page statique, ce type de demande similaire est de plus en plus émergente. Ces fonctions de planification des tâches aident les développeurs à mettre en œuvre une vérification périodique des formulaires, à retarder la synchronisation des données à distance ou des interactions d'interface utilisateur qui nécessitent des réponses retardées. Le nœud implémente également ces méthodes dans leur intégralité. Du côté du serveur, vous pouvez les utiliser pour répéter ou retarder l'exécution de nombreuses tâches, telles que l'expiration du cache, le nettoyage de la piscine de connexion, l'expiration de session, le sondage, etc.
Exécuter à l'aide de la fonction de retard settimeout
SetTimeout peut créer un plan d'exécution qui exécute la fonction spécifiée une fois à un certain moment à l'avenir, comme:
La copie de code est la suivante:
var timeout_ms = 2000; // 2 secondes
var timeout = setTimeout (function () {
Console.log ("Timed Out!");
}, timeout_ms);
Comme le client JavaScript, 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 une poignée de délai d'expiration, qui est un objet interne. Vous pouvez l'utiliser comme paramètre pour appeler ClearTimeout pour annuler la minuterie. Sauf cela, cette poignée n'a aucun effet.
Utilisez ClearTimeout pour annuler le plan d'exécution
Une fois la poignée de temps mort obtenue, vous pouvez utiliser Cleartimeout pour annuler le plan d'exécution de la fonction, comme ceci:
La copie de code est la suivante:
Var Timeouttime = 1000; // une seconde
var timeout = setTimeout (function () {
Console.log ("Timed Out!");
}, temps mort);
ClearTimeout (temps mort);
Dans cet exemple, la minuterie ne sera jamais déclenchée et ne sortira pas les mots "Time Out!". Vous pouvez également annuler le plan d'exécution à tout moment dans le futur, comme l'exemple suivant:
La copie de code est la suivante:
var timeout = setTimeout (fonction a () {
Console.log ("Timed Out!");
}, 2000);
setTimeout (fonction b () {
ClearTimeout (temps mort);
}, 1000);
Le code spécifie deux fonctions A et B qui sont exécutées retardées. La fonction A devrait être exécutée après 2 secondes, et B est prévu pour être exécuté après 1 seconde, car la fonction B est en premier, et elle annule le plan d'exécution de A, donc A ne s'exécutera jamais.
Élaborer et annuler le plan d'exécution répétitif de la fonction
SetInterval est similaire à Settimeout, mais il exécutera à plusieurs reprises une fonction à un intervalle de temps spécifié. Vous pouvez l'utiliser pour déclencher périodiquement un programme pour effectuer d'autres tâches qui doivent être répétées, telles que le nettoyage, la collecte, la journalisation, l'obtention de données, le sondage, etc.
Le code suivant sortira un "tick" à la console chaque seconde:
La copie de code est la suivante:
Période var = 1000; // 1 seconde
setInterval (function () {
Console.log ("Tick");
}, période);
Si vous ne voulez pas qu'il fonctionne pour toujours, vous pouvez utiliser ClearInterval () pour annuler la minuterie.
SetInterval renvoie une poignée de plan d'exécution, qui peut être utilisée comme paramètre pour effacer l'intervalle pour annuler le plan d'exécution:
La copie de code est la suivante:
var interval = setInterval (function () {
Console.log ("Tick");
}, 1000);
//…
ClearInterval (interval);
Utiliser Process.NextTtick pour retarder l'exécution de la fonction à la prochaine cycle de la boucle d'événement
Parfois, le programme JavaScript client utilise Settimeout (rappel, 0) pour retarder la tâche pendant une courte période. Le deuxième paramètre est de 0 millisecondes. Il dit à JavaScript d'exécuter cette fonction de rappel immédiatement après que tous les événements en attente sont traités. Parfois, cette technique est utilisée pour retarder l'exécution des opérations qui n'ont pas besoin d'être effectuées immédiatement. Par exemple, vous devez parfois commencer à jouer des animations ou faire d'autres calculs une fois l'événement utilisateur traité.
Dans Node, tout comme la signification littérale de la "boucle d'événement", la boucle d'événement fonctionne dans une boucle qui gère les files d'attente d'événements, et chaque tour de la boucle d'événement est appelée une tique.
Vous pouvez appeler la fonction de rappel une fois à chaque fois que la boucle de l'événement démarre l'exécution du tour suivant (Tick), qui est exactement le principe de Process.NextTick, et setTimeout, Settimeout utilise la file d'attente d'exécution à l'intérieur de l'exécution JavaScript, au lieu d'utiliser la boucle d'événement.
En utilisant Process.NextTick (rappel) au lieu de setTimeout (rappel, 0), votre fonction de rappel sera exécutée immédiatement après le traitement de l'événement dans la file d'attente. Il est beaucoup plus rapide que la file d'attente de délai d'expiration JavaScript (mesurée par le temps CPU).
Vous pouvez retarder la fonction jusqu'à la prochaine boucle d'événement et l'exécuter comme ceci:
La copie de code est la suivante:
process.NextTick (function () {
my_expensive_computation_function ();
});
Remarque: L'objet Process est l'un des rares objets globaux du nœud.
Boucle d'événement de blocage
Le runtime de Node et JavaScript utilise une boucle d'événement unique. Chaque boucle, le runtime utilise la fonction de rappel pour gérer l'événement suivant dans la file d'attente. Lorsque l'événement est exécuté, la boucle d'événement obtient le résultat d'exécution et traite l'événement suivant, répétant cela jusqu'à ce que la file d'attente de l'événement soit vide. Si l'un des rappels prend beaucoup de temps à s'exécuter, la boucle d'événement ne peut pas gérer d'autres événements en attente pendant cette période, 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 sensibles au processeur sont utilisées, la boucle d'événements deviendra lente et un grand nombre d'événements s'accumuleront, qui ne peuvent pas être traités dans le temps, ou même bloquer la file d'attente.
Voir l'exemple suivant de la boucle d'événements de blocage:
La copie de code est la suivante:
process.NextTick (fonction nextTick1 () {
var a = 0;
while (true) {
a ++;
}
});
process.NextTick (fonction nextTick2 () {
Console.log ("Next Tick");
});
setTimeout (fonction timeout () {
Console.log ("Timeout");
}, 1000);
Dans cet exemple, les fonctions NextTick2 et Timeout n'ont aucune chance de s'exécuter, peu importe combien de temps ils attendent, car la boucle d'événement est bloquée par la boucle infinie dans la fonction NextTick, et elle ne s'exécutera pas même si la fonction de délai d'expiration est prévue pour être exécutée après 1 seconde.
Lorsque setTimeout est utilisé, les fonctions de rappel sont ajoutées à la file d'attente du plan d'exécution, et dans ce cas, elles ne sont même pas ajoutées à la file d'attente. Bien qu'il s'agisse d'un exemple extrême, vous pouvez voir que l'exécution d'une tâche sensible au processeur peut bloquer ou ralentir la boucle d'événement.
Quitter la boucle d'événement
Utilisation de process.NextTick, une tâche non critique peut être reportée à la prochaine ronde de la boucle d'événements (Tick) avant l'exécution, qui peut libérer la boucle d'événement afin qu'il puisse continuer à exécuter d'autres événements en attente.
Voir l'exemple suivant. Si vous prévoyez 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 le retarder comme ceci:
La copie de code est la suivante:
stream.on ("data", fonction (data) {
Stream.end ("Ma réponse");
process.NextTick (function () {
fs.unlink ("/ path / to / file");
});
});
Utilisez SetTimeout au lieu de SetInterval pour assurer la sérialité de l'exécution de la fonction
Supposons que vous prévoyez 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 avoir l'intention de le faire exécuter périodiquement. Vous pouvez l'implémenter avec SetInterval comme ceci:
La copie de code est la suivante:
intervalle var = 1000;
setInterval (function () {
my_async_function (function () {
console.log ('my_async_function fini!');
});
}, interval); // Note du traducteur: j'ai ajouté le précédent ", interval" et l'auteur aurait dû le manquer à cause d'une faute de frappe
Vous devez être en mesure de vous assurer que ces fonctions ne sont pas exécutées simultanément, mais si vous utilisez SetInterval, vous ne pouvez pas garantir cela. Si la fonction my_async_function fonctionne un milliseconde plus longue que les variables d'intervalle, elles seront exécutées simultanément, plutôt que en série en séquence.
Note du traducteur: (La partie audacieuse ci-dessous est ajoutée par le traducteur, pas le contenu du livre original)
Pour faciliter la compréhension de cette partie du contenu, vous pouvez modifier le code de l'auteur afin qu'il puisse réellement s'exécuter:
La copie de code est la suivante:
intervalle var = 1000;
setInterval (function () {
(fonction my_async_function () {
setTimeout (function () {
console.log ("1");
}, 5000);
}) ();
},intervalle);
Exécutez ce code et vous constaterez qu'après avoir attendu 5 secondes, "Hello" est sorti toutes les 1 secondes. Nous nous attendons à ce qu'après l'exécution actuelle de My_async_Function (pris 5 secondes), attendez 1 seconde avant d'exécuter le prochain my_async_function, et l'intervalle entre chaque sortie doit être de 6 secondes. Ce résultat est dû au fait que my_async_function n'est pas exécuté en série, mais est exécuté en même temps.
Par conséquent, vous avez besoin d'un moyen de forcer l'intervalle entre la fin d'une exécution d'un my_async_function et le début de l'exécution du prochain my_async_function est exactement le temps spécifié par la variable d'intervalle. Vous pouvez faire ceci:
La copie de code est la suivante:
intervalle var = 1000; // 1 seconde
(Horaire des fonctions () {// Ligne 3
setTimeout (fonction do_it () {
my_async_function (function () {// ligne 5
console.log ('async est fait!');
calendrier();
});
}, interval);
} ()); // Ligne 10
Dans le code précédent, une fonction appelée calendrier (ligne 3) est déclarée et elle est appelée immédiatement après la déclaration (ligne 10). La fonction de planification exécutera la fonction DO_IT après 1 seconde (spécifiée par Interval). Après 1 seconde, la fonction my_async_function sur la ligne 5 sera appelée. Lorsqu'il est exécuté, il appellera sa propre fonction de rappel anonyme (ligne 6). Cette fonction de rappel anonyme réinitialisera à nouveau le plan d'exécution de DO_IT et le laissera exécuter à nouveau après 1 seconde, de sorte que le code commencera sériement et en continu.
résumé
Vous pouvez utiliser la fonction setTimeout () pour prédéfinir le plan d'exécution de la fonction et l'annuler avec la fonction cleartimeout (). Vous pouvez également utiliser setInterval () pour exécuter une certaine fonction périodiquement à plusieurs reprises. En conséquence, vous pouvez utiliser ClearInterval () pour annuler ce plan d'exécution répété.
Si la boucle d'événement est bloquée en utilisant une opération sensible au processeur, les fonctions qui devaient initialement être exécutées seront retardées et ne seront jamais exécutées. N'utilisez donc pas les opérations sensibles au CPU dans la boucle d'événement. Vous pouvez également utiliser Process.NextTick () pour retarder l'exécution de la fonction jusqu'au prochain tour de la boucle d'événement.
Lorsque vous utilisez des E / S et SetInterval (), vous ne pouvez pas garantir qu'il n'y a qu'un seul appel en attente à tout moment, mais vous pouvez utiliser des fonctions récursives et setTimeout () pour éviter ce problème délicat.