Maison  >  Article  >  interface Web  >  Explication détaillée de l'utilisation de minuteries pour exécuter régulièrement des fonctions dans Node.js_node.js

Explication détaillée de l'utilisation de minuteries pour exécuter régulièrement des fonctions dans Node.js_node.js

WBOY
WBOYoriginal
2016-05-16 16:39:341347parcourir

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 :

Copier le code Le code est le suivant :

var oneSecond = 1000 * 1; // une seconde = 1000 x 1 ms

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 :

Copier le code Le code est le suivant :

                var oneSecond = 1 000 * 1 ; // une seconde = 1 000 x 1 ms

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 :

Copier le code Le code est le suivant :

                      var timeout_ms = 2000 ; // 2 secondes

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 :

Copier le code Le code est le suivant :

                    var timeoutTime = 1000 ; // une seconde

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 :

Copier le code Le code est le suivant :

var timeout = setTimeout (fonction A() {

console.log("timed out!");

                       }, 2000);

                                       setTimeout(function B() {

                                                                                                                                                                                                                                                          
                     }, 1000);

Le code spécifie deux fonctions d'exécution retardée A et B. La fonction A est programmée pour être exécutée après 2 secondes, et B est programmée pour être exécutée après 1 seconde, car la fonction B est exécutée en premier et elle annule le plan d'exécution de A. donc A ne fonctionnera jamais.

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 :


Copier le code Le code est le suivant :
              var période = 1 000 ; // 1 seconde
setInterval(function() {

console.log("tick");

             }, point final);


Si vous ne voulez pas qu'il s'exécute indéfiniment, vous pouvez utiliser clearInterval() pour annuler le minuteur.

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 :

Copier le code Le code est le suivant :
                var intervalle = setInterval(function() {
console.log("tick");

             }, 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 :

Copier le code Le code est le suivant :

processus.nextTick(function() {

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 :

Copier le code Le code est le suivant :

processus.nextTick(function nextTick1() {

var a = 0;

while(true) {

un ;

                                                                                                                     }

             });

process.nextTick(function nextTick2() {

console.log("prochain tick");

             });

setTimeout(fonction timeout() {

console.log("timeout");

             }, 1000);


Dans cet exemple, les fonctions nextTick2 et timeout n'ont aucune chance de s'exécuter quel que soit le temps qu'elles attendent, car la boucle d'événements est bloquée par la boucle infinie de la fonction nextTick, même si l'exécution de la fonction timeout est prévue après. 1 seconde, il ne fonctionnera pas.

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 :


Copier le code Le code est le suivant :
                   stream.on("data", function(data) {
stream.end("ma réponse");

process.nextTick(function() {

fs.unlink("/chemin/vers/fichier");

                                                                                   } );

             });


Utilisez setTimeout au lieu de setInterval pour garantir la sérialité de l'exécution de la fonction

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 :

.

Copier le code Le code est le suivant :

              intervalle var = 1 000 ;

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


Vous devez être en mesure de vous assurer que ces fonctions ne seront pas exécutées en même temps, mais vous ne pouvez pas le garantir si vous utilisez setinterval. Si la fonction my_async_function prend une milliseconde de plus que la variable d'intervalle pour s'exécuter, elles seront exécutées. en même temps au lieu d'exécution en série.

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 :

Copier le code Le code est le suivant :
             intervalle var = 1 000 ;
setInterval(function(){

(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.

Par conséquent, vous avez besoin d'un moyen pour forcer l'intervalle entre la fin d'une exécution de my_async_function et le début de la suivante my_async_function à être exactement le temps spécifié par la variable d'intervalle. Vous pouvez faire ceci :


Copier le code Le code est le suivant :

                 intervalle var = 1 000 ; // 1 seconde

(function planning() { //Ligne 3

setTimeout(function do_it() {

my_async_function(function() { //Ligne 5

console.log('async is done!');

planning();

                                                                                                                                                                                   

                            }, intervalle);

                    }());


Dans le code précédent, une fonction appelée planning est déclarée (ligne 3), et elle est appelée immédiatement après la déclaration (ligne 10). La fonction planning exécutera la fonction do_it après 1 seconde (spécifiée par intervalle). Après 1 seconde, la fonction my_async_function sur la ligne 5 sera appelée. Une fois l'exécution terminée, sa propre fonction de rappel anonyme (ligne 6) sera appelée, et cette fonction de rappel anonyme réinitialisera à nouveau le plan d'exécution de do_it et la laissera être à nouveau exécutée. après 1 seconde, afin que le code commence à s'exécuter en série et en continu en boucle.

Résumé

Vous pouvez utiliser la fonction setTimeout() pour prédéfinir le plan d'exécution de la fonction et utiliser la fonction clearTimeout() pour l'annuler. Vous pouvez également utiliser setInterval() pour exécuter périodiquement une fonction à plusieurs reprises. En conséquence, vous pouvez utiliser clearInterval() pour annuler ce plan d'exécution répété.

Si la boucle d'événements est bloquée à l'aide d'une opération sensible au processeur, les fonctions dont l'exécution était initialement prévue seront retardées, voire jamais exécutées. N'utilisez donc pas d'opérations sensibles au processeur dans la boucle d'événements. Vous pouvez également utiliser process.nextTick() pour retarder l'exécution d'une fonction jusqu'à la prochaine itération de la boucle d'événements.

Lorsque les E/S sont utilisées avec setInterval(), vous ne pouvez pas garantir qu'il n'y aura qu'un seul appel en attente à tout moment. Cependant, vous pouvez utiliser des fonctions récursives et la fonction setTimeout() pour éviter ce problème délicat.

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn