Javascript est connu pour être un seul thread dans tous les navigateur moderne implémentations, mais est-ce que spécifiées dans une norme ou est-ce juste par tradition? Est-il totalement sûr de supposer que le javascript est toujours mono-thread?
Réponses
Trop de publicités?C'est une bonne question. J'aimerais dire "oui". Je ne peux pas.
JavaScript est généralement considéré comme ayant un seul thread d'exécution visible pour les scripts(*), de sorte que lorsque votre script en ligne de l'écouteur d'événement ou de l'expiration de est entré, vous restez complètement dans le contrôle jusqu'à ce que vous renvoyer à partir de la fin de votre bloc ou de la fonction.
(*: en ignorant la question de savoir si les navigateurs vraiment mettre en œuvre leur JS moteurs à l'aide d'un OS-fil, ou si d'autres threads d'exécution sont introduites par les web workers.)
Cependant, dans la réalité, ce n'est pas tout à fait vrai, dans sournois vilaines manières.
Le cas le plus fréquent est immédiate des événements. Les navigateurs feu ces immédiatement lorsque votre code n'a quelque chose à cause d'eux:
<textarea id="log" rows="20" cols="40"></textarea>
<input id="inp">
<script type="text/javascript">
var l= document.getElementById('log');
var i= document.getElementById('inp');
i.onblur= function() {
l.value+= 'blur\n';
};
setTimeout(function() {
l.value+= 'log in\n';
l.focus();
l.value+= 'log out\n';
}, 100);
i.focus();
</script>
Résultats en log in, blur, log out
sur tous sauf IE. Ces événements ne sont pas seulement le feu parce que vous avez appelé, focus()
directement, ils pourraient se produire parce que vous avez appelé, alert()
, ou ouvre une fenêtre pop-up, ou tout autre chose qui se déplace le focus.
Cela peut également donner lieu à d'autres événements. Par exemple, ajouter un i.onchange
écouteur et tapez quelque chose dans l'entrée avant l' focus()
appel unfocuses, et le journal de l'ordre est - log in, change, blur, log out
, à l'exception de l'Opéra où il est log in, blur, log out, change
et à savoir où il est (encore moins explicably) log in, change, log out, blur
.
De la même façon appelant click()
sur un élément qui fournit les appels de l' onclick
gestionnaire immédiatement dans tous les navigateurs (au moins c'est cohérent!).
(Je suis en utilisant le direct, on...
gestionnaire d'événement propriétés ici, mais la même chose se passe avec addEventListener
et attachEvent
.)
Il y a aussi un tas de circonstances dans lesquelles les événements peuvent le feu tandis que votre code est filetée, en dépit de vous avoir fait rien pour le provoquer. Un exemple:
<textarea id="log" rows="20" cols="40"></textarea>
<button id="act">alert</button>
<script type="text/javascript">
var l= document.getElementById('log');
document.getElementById('act').onclick= function() {
l.value+= 'alert in\n';
alert('alert!');
l.value+= 'alert out\n';
};
window.onresize= function() {
l.value+= 'resize\n';
};
</script>
Frapper alert
et vous obtiendrez une boîte de dialogue modale. Pas de plus le script s'exécute jusqu'à ce que vous fermez le dialogue, oui? Nope. Redimensionner la fenêtre principale et vous obtiendrez alert in, resize, alert out
dans le textarea.
Vous pourriez penser qu'il est impossible de redimensionner une fenêtre, tandis qu'une boîte de dialogue modale est en hausse, mais pas tellement: dans Linux, vous pouvez redimensionner la fenêtre autant que vous le souhaitez; sur Windows, c'est pas si facile, mais vous pouvez le faire en changeant la résolution de l'écran à partir d'un plus grand à plus petit où la fenêtre ne rentre pas, à l'origine pour obtenir redimensionné.
Vous pourriez penser que, bien, c'est seulement resize
(et sans doute un peu plus comme scroll
) qui peut se déclenche lorsque l'utilisateur ne dispose pas d'une interaction active avec le navigateur, car le script est filetée. Et pour windows vous avez peut-être raison. Mais pour que tout se passe à la casserole dès que vous êtes en train de faire de la croix-fenêtre de script. Pour tous les navigateurs autre que Safari, qui bloque toutes les fenêtres/onglets/images lors de l'une d'entre elles est occupée, vous pouvez interagir avec un document à partir du code d'un autre document, s'exécute dans un thread séparé de l'exécution et de causer de tout événement lié aux gestionnaires de feu.
Des endroits où des événements que vous pouvez causer à être généré peut être si un script est toujours filetée:
lorsque le modal popups (
alert
,confirm
,prompt
) sont ouvertes, dans tous les navigateurs, mais l'Opéra;au cours
showModalDialog
sur les navigateurs qui le supportent;"Un script sur cette page est peut-être occupé..." de la boîte de dialogue, même si vous choisissez de laisser le script de continuer à exécuter, permet à des événements comme le redimensionnement et le flou à feu et à être traités, même alors que le script est dans le milieu d'une longue boucle, à l'exception de l'Opéra.
il y a un moment pour moi, c'est à dire avec le Soleil Plugin Java, tout appel de méthode sur un applet pourrait autoriser les manifestations d'incendie et de script de saisir de nouveau. C'était toujours un moment sensible de bug, et il est possible de Sun ont fixé depuis (je l'espère).
probablement plus. Il a été un moment depuis que j'ai testé cela et les navigateurs ont gagné en complexité depuis.
En résumé, le JavaScript semble que la plupart des utilisateurs, la plupart du temps, d'avoir un strict event-driven seul thread d'exécution. En réalité, il n'a pas une telle chose. Il n'est pas clair comment cela est-il tout simplement d'un bug et la façon dont beaucoup d'une action délibérée, mais si vous écrivez des applications complexes, en particulier croix-fenêtre/cadre-de script, il ya toutes les chances qu'il pourrait vous mordre et intermittent, dur-à-debug façons.
Si le pire arrive au pire, vous pouvez résoudre les problèmes de simultanéité par indirecting toutes les réponses aux événements. Lorsqu'un événement arrive, les déposer dans une file d'attente et de traiter la file d'attente dans l'ordre plus tard, en setInterval
fonction. Si vous écrivez un cadre que vous avez l'intention d'être utilisé par les applications complexes, il pourrait être une bonne chose. postMessage
sera aussi sans doute à soulager la douleur de la croix-document de scripting dans l'avenir.
Je dirais oui, parce que pratiquement tous les (au moins tous les non-trivial) code javascript serait briser si un navigateur du moteur javascript ont été à l'exécuter de manière asynchrone.
Ajoutez à cela le fait que HTML5 précise déjà des Web workers (explicite, normalisés de l'API pour le multi-threading code javascript) l'introduction du multi-threading dans le code Javascript de base seraient pour la plupart inutiles.
(Note pour les autres commentateurs: Même si setTimeout/setInterval
, HTTP-request événements onload (XHR), de l'INTERFACE et des événements (clic, focus, etc.) fournir un brut impression de multi-threadedness - ils sont encore tous exécutés le long d'un seul scénario - un à un - donc, même si nous ne savons pas leur ordre d'exécution à l'avance, il n'y a pas besoin de s'inquiéter à propos des conditions externes de changement au cours de l'exécution d'un gestionnaire d'événement, programmé la fonction ou XHR de rappel.)
JavaScript/ECMAScript est conçu pour vivre dans un environnement hôte. C'est, JavaScript n'est pas réellement faire quelque chose , à moins que l'hôte de l'environnement décide de les analyser et d'exécuter un script, et de fournir de l'environnement des objets qui permettent de JavaScript en fait être utiles (comme les DOM dans les navigateurs).
Je pense que d'une fonction ou d'un bloc de script va exécuter ligne par ligne et qui est garanti pour le JavaScript. Cependant, peut-être un environnement hôte peut exécuter plusieurs scripts en même temps. Ou, un environnement hôte peut toujours fournir un objet qui fournit le multi-threading. setTimeout
et setInterval
sont des exemples, ou au moins pseudo-exemples, d'un environnement d'accueil offrant un moyen de faire certains de la concurrence (même si ce n'est pas exactement de la simultanéité).