2009-09-01 4 views
13

En javascript, est-il différent entre ces deux:MyFunction() vs window.setTimeout ('MyFunction()', 0)?

// call MyFunction normal way 

MyFunction(); 

// call MyFunction with setTimeout to 0 // 

window.setTimeout('MyFunction()', 0); 

La raison pour laquelle j'ai demandé était parce que récemment tombé sur la situation où le code ne fonctionne que si j'utilise setTimeout(0) pour appeler la fonction. Pour ma compréhension, setTimeout(0) est exactement le même que d'appeler une fonction directement parce que vous ne définissez aucun délai. Mais à partir de ce que je vois comment cela fonctionne dans le code, setTimeout(0) semble être exécuté en dernier.

Est-ce que quelqu'un peut clarifier exactement comment setTimeout(0) est vraiment appelé dans l'ordre des autres appels de fonction?

+1

http: // stackoverflow.com/questions/779379/why-does-settimeoutfn-0-parfois-aide –

Répondre

17

setTimeout() provoque toujours la mise en file d'attente du bloc de JavaScript à exécuter. Il s'agit de savoir quand il sera exécuté, ce qui est décidé par le délai prévu. Si vous appelez setTimeout() avec un délai de 0, l'interpréteur JavaScript se rendra compte qu'il est actuellement occupé (exécutant la fonction en cours) et l'interpréteur programmera le bloc de script à exécuter une fois que la pile d'appels actuelle sera vide (sauf il y a d'autres blocs de script qui sont également mis en file d'attente).

La pile d'appels peut prendre beaucoup de temps à se vider, ce qui explique pourquoi l'exécution est retardée. Cela est principalement dû à la nature mono-thread de JavaScript dans un contexte de fenêtre unique. Par souci d'exhaustivité, MyFunction() exécutera immédiatement la fonction. Il n'y aura pas de file d'attente impliquée.

PS: John Resig has some useful notes on how the JavaScript timing mechanism works. La raison pour laquelle votre code "semble fonctionner" uniquement lorsque vous utilisez setTimeout (fn(), 0) est que les navigateurs ne peuvent mettre à jour le DOM que lorsque la pile d'appels en cours est terminée. Par conséquent, le prochain bloc JavaScript reconnaîtra les changements DOM, ce qui est tout à fait possible dans votre cas. Un rappel setTimeout() crée toujours une nouvelle pile d'appels.

3

Je suppose que le délai d'attente ne commence que lorsque la page est entièrement chargée, alors qu'un simple 'MyFunction()' s'exécutera dès qu'il est traité.

+1

C'est correct. Pas besoin de deviner. –

+1

@Marius configure une page de test et essaie-la: les fonctions inline se déclencheront tout au long de la page avant qu'un setTimeout (0) déclaré en haut ne se déclenche. –

+0

J'ai essayé, vous aviez raison, et supprimé mon commentaire, mais pas avant que vous l'ayez vu. – Marius

0

La minuterie va essayer d'exécuter une fois que votre thread actuel est terminé. Cela dépend de l'endroit où vous appelez window.setTimeout(). S'il s'agit d'une balise javascript, mais pas à l'intérieur d'une fonction, elle sera appelée dès que la fin de la balise javascript sera atteinte. Par exemple:

<html> 
<script type="text/javascript"> 
setTimeout(function(){alert("hello")},0); 
var d=Number(new Date())+1000; 
while(Number(new Date())<d){ 

} 
alert("hi"); 
</script> 
</html> 

Si vous appelez la setTimeout dans une fonction qui résulte de ce qu'un événement, par exemple onload, il attendra que le retour de la fonction de gestionnaire d'événements:

<html> 
<script type="text/javascript"> 
document.addEventListener("mousedown",function(){ 
    setTimeout(function(){alert("hello")},0); 
    var d=Number(new Date())+1000; 
    while(Number(new Date())<d){ 

    } 
    alert("hi"); 
}, true); 
</script> 
</html> 

Il est impossible faire qu'un thread en JavaScript attend pendant qu'un autre thread est en cours d'exécution. Les écouteurs d'événements attendent que le thread en cours soit terminé avant de commencer à s'exécuter. La seule exception est Web Workers, mais ils s'exécutent dans un fichier différent, et la seule façon de communiquer entre eux est d'utiliser des écouteurs d'événement, alors que vous pouvez envoyer un message pendant que l'autre fonctionne, il ne recevra pas ce message jusqu'à ce qu'il soit fait, ou il vérifie manuellement les messages.

+0

Tout ce que vous dites est correct au sens général (JavaScript est monothread) mais setTimeout (0) se déclenche quand la page est chargée, pas quand elle atteint la fin du bloc de script. –