web-dev-qa-db-fra.com

Comment fonctionnent setInterval et setTimeout?

j'étais dans une situation délicate,

Je travaille avec du JavaScript pur depuis près de 3 ans et je sais que JavaScript est un langage monothread , et que vous pouvez simuler une exécution asynchrone en utilisant setInterval et setTimeout,

mais quand j'ai pensé à comment ils pouvaient fonctionner, je ne pouvais pas le comprendre clairement. Alors, comment ces fonctions affectent le contexte d'exécution?

Je suppose que dans un temps spécifique ne s'exécute qu'une partie du code et après qu'il passe à une autre partie. Si tel est le cas, un grand nombre d'appels setInterval ou setTimeout affecteront-ils les performances?

28
Taron Mehrabyan

Javascript est un thread unique, mais pas le navigateur. Le navigateur a au moins trois threads: thread de moteur Javascript, thread d'interface utilisateur et thread de synchronisation, où la synchronisation de setTimeout et setInterval est effectuée par le thread de synchronisation.

Lors de l'appel de setTimeout ou setInterval, un thread de minuterie dans le navigateur commence le compte à rebours et lorsque le temps passe place la fonction de rappel dans la pile d'exécution du thread javascript. La fonction de rappel n'est pas exécutée avant la fin des autres fonctions au-dessus dans la pile. Par conséquent, s'il existe d'autres fonctions chronophages en cours d'exécution lorsque le temps est écoulé, le rappel de setTimeout ne se terminera pas à temps.

23
CDT

Fonctionnement de setTimeout/setInterval en JavaScript

Le navigateur possède une API pour la fonction Timer, tout comme l'API pour l'événement ex.

'Cliquez sur'

'faire défiler'

Supposons que vous ayez le code suivant dans votre application

function listener(){
    ...
}

setTimeout(listener, 300)

function foo(){
    for(var i = 0; i < 10000; i++){
        console.log(i)
    }
}

foo()

See How Function Execution work's in javascript

À ce stade, selon notre code, nous avons écrit au-dessus de notre pile d'appels ressemblera

Pile d'appels -> foo

Et supposons que foo prendra 1s pour terminer son exécution, comme nous avons déjà défini 1 timeout dans notre code et nous l'exécutons avant que "foo" ne termine son exécution, c'est-à-dire à 300 ms

Que se passera-t-il alors?

Javascript arrête-t-il d'exécuter foo et commence-t-il à exécuter setTimeout?

Non

Comme nous savons déjà que javascript est un thread unique, il doit donc terminer l'exécution de foo avant d'aller de l'avant, mais comment le navigateur s'assure-t-il qu'après l'exécution de foo le "setTimeout" s'exécutera?

Ici, la magie javascript entre en scène

Lorsque 300 ms est expiré, le "Timer API" du navigateur entre en action et place le gestionnaire de délai d'attente dans "Message Queue"

À ce stade, "Message Queue" dans l'image ci-dessus ressemblera

Message Queue -> setTimout: listner

Et

Pile d'appels -> foo

Et lorsque "Call Stack" devient vide, c'est-à-dire que foo termine son exécution, la "Event Loop" comme indiqué dans l'image prendra le message de la file d'attente de messages et le poussera dans la pile

Le seul travail de "Boucle d'événement" est lorsque "Pile d'appels" devient vide et que "File d'attente de messages" y est entré, puis retirez le formulaire de message "File d'attente de messages" et poussez-le dans "Pile d'appels"

À ce stade, la file d'attente de messages dans l'image ci-dessus ressemblera

File d'attente des messages ->

Et

Pile d'appels -> auditeur

Et c'est ainsi que setTimeout et setInterval fonctionnent, même si nous spécifions 300 ms dans setTimeout, il s'exécutera une fois que "foo" aura terminé son exécution dans ce cas, c'est-à-dire après 1s. Et c'est pourquoi la minuterie spécifiée dans setTimeout/setInterval indique "Minimum Time" délai pour l'exécution de la fonction.

8
Jay Bidwai

Javascript est un thread unique, mais pas le navigateur.

Il y a 1 pile où la fonction et les instructions sont exécutées. il y a 1 file d'attente où la fonction est mise en file d'attente pour être exécutée. il existe des API Web qui peuvent contenir la fonction pendant un temps particulier, définies dans setTimeout et setInterval dans la table des événements.

lorsque le moteur javascript exécute le fichier js ligne par ligne, s'il trouve une ligne comme instruction ou fonction, il la charge sur la pile et s'exécute mais s'il s'agit d'un appel setTimeout ou setInterval, le gestionnaire de fonctions associé à setTimeout ou setInterval est retiré par l'API TIME (une des API Web du navigateur) et maintenez-la pendant ce temps.

Une fois ce temps écoulé, Time Api met cette fonction en fin de file d'attente d'exécution.

Maintenant, l'exécution de cette fonction dépend d'autres appels de fonctions qui sont en avance dans la file d'attente.

Remarque: cet appel de fonction est appelé sur un objet window.

setTimeout(function () {console.log(this)}, 300)

Fenêtre {postMessage: ƒ, flou: ƒ, focus: ƒ, fermeture: ƒ, cadres: fenêtre,…}

3
Samyak Jain

JavaScript est un langage de script à thread unique, il peut donc exécuter un morceau de code à la fois (en raison de sa nature à thread unique), chacun de ces blocs de code "bloque" la progression d'autres événements asynchrones. Cela signifie que lorsqu'un événement asynchrone se produit (comme un clic de souris, un déclenchement de minuterie ou une fin de XMLHttpRequest), il est mis en file d'attente pour être exécuté plus tard.

setTimeout () lorsque vous utilisez setTimeout (), il ne s'exécutera que lorsque son tour arrivera dans une file d'attente, si un événement antérieur (de setTimeout) se bloque pour une raison quelconque setTimeout peut être retardé par rapport au temps spécifié dans Fonction setTimeout (). lors de l'exécution de la fonction de rappel setTimeout, si un événement se produit (par exemple, un événement de clic), il est mis en file d'attente pour être exécuté plus tard.

setTimeout(function(){
  /* Some long block of code... */
  setTimeout(arguments.callee, 10);
}, 10);

setInterval(function(){
  /* Some long block of code... */
}, 10);

setInterval ()

  • Similaire à setTimeout mais appelle continuellement la fonction (avec un retard à chaque fois) jusqu'à ce qu'elle soit annulée.

  • le code setTimeout aura toujours un délai d'au moins 10 ms après la
    exécution de rappel précédente (cela peut finir par être plus, mais jamais moins) alors que setInterval tentera d'exécuter un rappel toutes les 10 ms, indépendamment du moment où le dernier rappel a été exécuté.

  • Si une minuterie est bloquée pour s'exécuter immédiatement, elle sera retardée
    jusqu'au prochain point d'exécution possible (qui sera plus long que le délai souhaité). Les intervalles peuvent s'exécuter consécutivement sans délai s'ils prennent suffisamment de temps pour s'exécuter (plus long que le délai spécifié).
    retard).

1
Ravi Patel

Juste une note en ce qui concerne mon expérience, si vous allez utiliser setTimeout (), la fonction sera toujours retardée (et je veux dire exécutée plus tard) ou exécutée après un code supplémentaire qui n'est pas 'expiré'. Cela peut se produire même avec des fonctions qui ont delay = 0 et qui sont provoquées par la boucle d'événement.

Voir l'exemple ci-dessous:

setTimeout(function() {
    console.log('Second');
}, 0)

console.log('First');
1
ptylek