38 votes

Que se passe-t-il en JavaScript lorsqu'un appel AJAX est renvoyé pendant l'exécution du script?

Supposons que j'écrive du code JavaScript exécutant un appel AJAX avec myCallback tant que méthode de rappel à exécuter lorsque l'opération AJAX aboutit.

Supposons alors qu'une autre méthode JavaScript appelée myFunction est appelée sur ma page lorsque myCallback est appelé de manière asynchrone.

Une opération a-t-elle préséance sur l'autre? Est-ce qu'ils courent tous les deux en même temps? Ce qui se produit?

56voto

T.J. Crowder Points 285826

Supposons ensuite qu'une autre méthode JavaScript appelé myFunction est appelée sur ma page lorsque myCallback est appelée de façon asynchrone.

Ne une opération de l'emporter sur les autres? Faire les deux fonctionnent en même temps? Ce qui se passe?

JavaScript dans les navigateurs est monothread (sauf à l'aide de votre web des travailleurs, et la syntaxe qui est explicite). Donc, myFunction sera exécuté jusqu'à ce qu'il retourne avec certaines mises en garde (continuer à lire). Si la couche ajax effectue une opération tout en myFunction est en marche (ce qui peut très bien), et elle doit appeler la fonction de rappel, que l'appel est en attente. La prochaine fois que votre code rendements, l'appel suivant dans la file d'attente va être déclenchée.

Il semble, alors, que nous n'avons jamais à vous soucier des conditions de course. C'est surtout vrai, mais il y a des subtilités. Considérez par exemple ce code:

var img = document.createElement('img');
img.src = /* ...the URL of the image... */;
img.onload = function() {
    // Handle the fact the image loaded
    foo();
};
doSomethingElse();
doYetAnotherThing();

Depuis JavaScript dans les navigateurs est mono-thread, je suis assuré d'obtenir l' load cas lorsque l'image est chargée, droite?

Mal.

Le JavaScript code est mono-thread, mais le reste de l'environnement n'est probablement pas. Ainsi, il peut arriver que, après avoir défini la img.src, le navigateur peut voir qu'il a une copie en cache de l'image, on peut utiliser, et si elle déclenche le load d'un événement sur l' img entre l' img.src = ... ligne et l' img.onload = ... ligne de. Depuis mon gestionnaire n'est pas attaché, je n'ai pas l'appeler, parce que par moment j'ai joint mon gestionnaire, l'événement a déjà tiré.

Mais vous pouvez voir l'effet de la mise en attente si l'on inverse ces lignes:

var img = document.createElement('img');
img.onload = function() {
    // Handle the fact the image loaded
    foo();
};
img.src = /* ...the URL of the image... */;
doSomethingElse();
doYetAnotherThing();

Maintenant, je suis d'accroche de l'événement avant de paramètre src. Si l'événement se déclenche entre l' img.src = ... ligne et l' doSomethingElse ligne (parce que le navigateur a l'image dans le cache), le rappel de mon handler se met en file d'attente. doSomethingElse et doYetAnotherThing exécuté avant mon gestionnaire. Uniquement lorsque le contrôle est passé de mon code ne la le d'attente appel à mon gestionnaire de finalement se faire rouler. Le code JavaScript est mono-thread, mais l'environnement n'est pas.

Vous pouvez également donner à l'hôte de l'environnement de manière non évidente. Par exemple, en appelant alert ou de ses breathren confirm, prompt, etc. Ces fonctions tenir comme les maux de pouces, ils sont modernes JavaScript parce qu'ils ne sont pas guidés par les événements; au lieu de cela, exécution de JavaScript est suspendue pendant une fenêtre modale est affichée. Mais comme bobince points dans sa discussion en profondeur ici, cela ne signifie pas qu'aucun autre code sera exécuté alors que le modal est à l'affiche. C'est toujours mono-thread, mais le fil conducteur est suspendu dans un endroit (par le modal) et utilisé pour exécuter du code ailleurs dans le temps; une très belle distinction, en effet. (Bob aussi des points à certaines de gestion des événements — son focus exemple — qui semble briser cette règle, mais il ne le fait pas. Son exemple les appels focus, qui appelle à son tour les gestionnaires d'événements, puis retourne; pas différents de vous appeler vos propres fonctions.) La chose à retenir les éléments que Bob points ont en commun, c'est que votre code a appelé dans quelque chose dans l'environnement d'accueil qui ne s'en va et fait quelque chose (qui affiche une boîte de dialogue modale, les incendies blur et focus des gestionnaires, etc.).

(alert et son breathren en particulier de provoquer toutes sortes de méchanceté, en particulier autour de la focus et blur, et je vous recommande de les éviter au profit de techniques plus modernes (qui peut aussi regarder sur 18x mieux).)

Donc, ce sont les mises en garde mentionnées au début de la réponse. Et en particulier, si l' myFunction des appels alert, au moins sur Firefox, l'ajax d'achèvement de rappel va se faire au cours de l' alert (il ne sera pas sur la plupart des autres navigateurs). Si vous êtes curieux de découvrir ce qui fonctionne et ne se produit pas lors d' alerts et autres, voici une page de test test setTimeout et ajax; vous pouvez étendre les tests d'aller plus loin.

7voto

ninjagecko Points 25709

Ces réponses sont toutes dans l'erreur [edit: au moins 3-4 mal lorsque cette réponse a été publiée]. Le XHR événement est mis dans la file d'attente d'événements/la piscine. Lorsque le single-threaded javascript fil n'est pas occupé, il saisira les prochains événements à partir de l'événement de la piscine, et d'agir sur eux. L'un de ces événements sera votre XHR "AJAX" demande, ce qui va déclencher le rappel, qui sera ensuite exécuter. C'est de cette façon tous les event-driven systèmes sans interruptions de travail.

edit: Upvoting de la réponse de Joe qui relie le javascript Est garanti d'être mono-thread? et mentionne la subtile pointe-cas. Très instructif.

3voto

Joe Points 34413

Javascript type de thread unique voir Est-ce que javascript est garanti pour être mono-thread? . Donc, la réponse est NON, votre gestionnaire d'événements et votre fonction peuvent s'exécuter en même temps, ou non.

2voto

icktoofay Points 60218

Le rappel AJAX s'exécute sur la prochaine boucle d'événements.

0voto

Brad Ruderman Points 195

Les appels ajax seront simultanément. Ainsi, lorsque l'appel ajax aboutit, la fonction de rappel est appelée, qui à son tour appelle la fonction my.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X