Maison  >  Article  >  interface Web  >  Exemples pour expliquer setTimeout pour voir le processus d'exécution de la fonction js

Exemples pour expliquer setTimeout pour voir le processus d'exécution de la fonction js

小云云
小云云original
2017-12-20 09:27:121990parcourir

La méthode setTimeout est utilisée pour appeler une fonction ou une expression calculée après un nombre spécifié de millisecondes. Cet article présente principalement le processus d'exécution de la fonction js de setTimeout. Les amis qui en ont besoin peuvent s'y référer. J'espère que cela pourra aider tout le monde.


for (var i = 0; i < 5; i++) {
      setTimeout(function () {
        console.log(i)
      }, i * 1000);
    }
    console.log(i);

Quoi ? N'est-ce pas la méthode de mise en œuvre que j'ai vue il y a longtemps consistant à imprimer un 5, puis un 5, puis à imprimer un 5 toutes les secondes jusqu'à ce que 6 5 soient imprimés ? Alors voici la question, que dois-je faire si je veux imprimer 0, 1, 2, 3, 4, 5 en séquence ? En fait, je savais qu'il y avait ces deux méthodes avant : l'une est comme ceci :


function log(i){
setTimeout(function(){
console.log(i)
},i*1000)
};
for (var i = 0; i < 5; i++) {
      log(i) ;
    }
    console.log(i);

Il y en a un autre comme celui-ci :


for(var i=0;i<5;i++){
(function(e){
setTimeout(function(){
console.log(e)
},i*1000);
})(i);
};
console.log(i);

Je n'ai pas peur des blagues. Je n'avais pas compris ces deux-là avant. Quelle est la vraie fonction de la fonction ? Je me force juste à m'en souvenir et à la modifier comme ça, mais ça ne marche pas maintenant. Donc, je l'ai lentement analysé et j'ai découvert que le code ci-dessus peut être séparé en ceci :

i=0; lorsque la condition est remplie


setTimeout(function(){
console.log(i)
},0*1000);
i=1 ; satisfaire à la condition


setTimeout(function(){
console.log(i)
},1*1000);
i=2 ; satisfaire à la condition ; >

Quand i=3; la condition est remplie


setTimeout(function(){
console.log(i)
},2*1000);

Quand i=4; >


Lorsque i=5, la condition n'est pas remplie, sortez de la boucle, puis exécutez console.log(i) après la boucle for, en imprimant 5 enfin, imprimez 5 toutes les secondes ; ;

setTimeout(function(){
console.log(i)
},3*1000);
C'est vraiment intéressant, pourquoi le console.log à l'intérieur de setTimeout sera-t-il exécuté après le console.log en dehors de la boucle for ? Jusqu'à ce que je réalise le mot => "file d'attente", les files d'attente sont divisées en file d'attente de tâches macro (Macro Task) et en file d'attente de micro tâches (Micro Task). En javascript :

la macro-tâche comprend : script (Code global). , setTimeout, setInterval, setImmediate, I/O, rendu de l'interface utilisateur.


la micro-tâche comprend : process.nextTick, Promises, Object.observe, MutationObserver

setTimeout(function(){
console.log(i)
},4*1000);
Le setTimeout de la fonction ci-dessus appartient à la tâche macro

En js, l'ordre de la boucle d'événement La première boucle démarre à partir du script, puis le contexte global entre dans la pile d'appel de fonction Lorsqu'une macro-tâche est rencontrée, elle est transmise au module qui la gère. Après traitement, la fonction de rappel est mise en place. la file d'attente de la macro-tâche Lorsqu'une micro-tâche est rencontrée, -task place également sa fonction de rappel dans la file d'attente des micro-tâches. Jusqu'à ce que la pile d'appels de fonction soit effacée et qu'il ne reste que le contexte d'exécution global, toutes les micro-tâches commencent à être exécutées. Une fois que toutes les micro-tâches exécutables ont été exécutées. La boucle exécute à nouveau une file d'attente de tâches dans la macro-tâche, puis exécute toutes les micro-tâches après l'exécution, et la boucle continue.

C'est pourquoi le console.log à l'intérieur de setTimeout sera exécuté après le console.log en dehors de la boucle for. Dans le contexte d'exécution de la fonction, la fonction seiTimeout sera placée dans la file d'attente pour traiter sa macro-tâche. , donc la fonction dans setTimeout ne sera pas exécutée pendant la boucle, mais attendra que tout le code global (hors file d'attente) soit terminé avant que la fonction dans la file d'attente ne soit exécutée en écrivant ceci, je suis peut-être un peu confus, dans en fait, moi aussi Un peu confus, hahaha ! !

Afin d'approfondir votre compréhension, vous pouvez également essayer d'y ajouter Promise, alors voici ceci :

Expliquez-le=>

1. Tout d'abord, la source de la tâche de script est exécutée en premier et le contexte global est poussé sur la pile.

2. Lorsque le code source de la tâche de script rencontre setTimeout lors de l'exécution, en tant que macro-tâche, il place sa fonction de rappel dans sa propre file d'attente.


3. Le code de la source de la tâche de script rencontre une instance Promise lors de l'exécution. Le premier paramètre du constructeur Promise est que la tâche en cours ne sera pas mise dans la file d'attente si elle est exécutée directement, donc 1 est affiché à ce moment-là.

(function copy() {
  setTimeout(function() {console.log(4)}, 0);
  new Promise(function executor(resolve) {
    console.log(1);
    for( var i=0 ; i<10000 ; i++ ) {
      i == 9999 && resolve();
    }
    console.log(2);
  }).then(function() {
    console.log(5);
  });
  console.log(3);
})()
4. Lorsque vous rencontrez la fonction de résolution dans la boucle for, la fonction est poussée dans la pile puis ressorte. À ce moment, le statut de Promesse devient Réalisé. Le code s'exécute ensuite et rencontre console.log(2), qui génère 2.

5. Ensuite, exécutez, le code rencontre la méthode then, et sa fonction de rappel est poussée sur la pile en tant que micro-tâche et entre dans la file d'attente des tâches de Promise. À ce moment, la fonction de rappel de fonction est alors. de Promise et la fonction dans setTimeout Les fonctions de rappel ont la même signification et seront placées dans leurs files d'attente de tâches respectives

Elles ne seront exécutées qu'après le contexte de la fonction, c'est-à-dire tout le code hors file d'attente dans le. script, a été exécuté. De plus, la file d'attente des microtâches est prioritaire sur la file d'attente des macrotâches Traitement,

La séquence globale est : code de contexte hors file d'attente > code de fonction de rappel de la file d'attente des microtâches > code de la fonction de rappel de la file d'attente des macrotâches

6. Le code continue de s'exécuter et la console est rencontrée à ce moment-là, log(3), sortie 3.

7. Après la sortie de 3, le code du premier script de macrotâche est exécuté. À ce moment, toutes les micro-tâches de la file d'attente commencent à être exécutées. Ensuite, la fonction de rappel est poussée sur la pile puis extraite. À ce moment, 5

8 est affiché. À ce moment, toutes les micro-tâches sont terminées et le premier cycle se termine. Le deuxième tour de boucle commence à partir de la file d'attente des tâches de setTimeout. La fonction de rappel de setTimeout est poussée dans la pile puis ressorte. À ce moment, 4 est affiché.

Enfin, afin d'approfondir la compréhension, voici un autre morceau de code :

console.log(&#39;golb1&#39;);
setTimeout(function() {
  console.log(&#39;timeout1&#39;);
  new Promise(function(resolve) {
    console.log(&#39;timeout1_promise&#39;);
    resolve();
    setTimeout(function(){
      console.log(&#39;time_timeout&#39;)
    });  
  }).then(function() {
    console.log(&#39;timeout1_then&#39;)
  })
  setTimeout(function() {
   console.log(&#39;timeout1_timeout1&#39;);
  });
})
new Promise(function(resolve) {
  console.log(&#39;glob1_promise&#39;);
  resolve();
  setTimeout(function(){
     console.log(&#39;prp_timeout&#39;)
    });
}).then(function() { console.log(&#39;glob1_then&#39;) })

如果你的执行结果是:golb1=>glob1_promise=>glob1_then=>timeout1=>timeout1_promise=>timeout1_then=>prp_timeout=>time_timeout=>timeout1_timeout1,

可能异步队列算是入门了吧!~~上面的代码看起来有点杂乱,可能用asyns搭配await改造一下会更好,但是这或多或少是鄙人从setTimeout中得到的见解吧

相关推荐:

JavaScript中setTimeout()的使用详解

js中的setTimeout()函数

JavaScript如何使用setTimeout来实现轮循动画的实例详解

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

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