web-dev-qa-db-fra.com

Comment JavaScript gère-t-il les réponses AJAX en arrière-plan?

Étant donné que JavaScript s'exécute dans un seul thread, après qu'une demande AJAX est effectuée, que se passe-t-il réellement en arrière-plan? Je voudrais en savoir plus, est-ce que quelqu'un peut faire la lumière?

136
aziz punjani

Sous les couvertures, javascript a une file d'attente d'événements. Chaque fois qu'un thread d'exécution javascript se termine, il vérifie s'il y a un autre événement dans la file d'attente à traiter. S'il existe, il le retire de la file d'attente et déclenche cet événement (comme un clic de souris, par exemple).

La mise en réseau de code natif qui se trouve sous l'appel ajax saura quand la réponse ajax est terminée et un événement sera ajouté à la file d'attente d'événements javascript. La façon dont le code natif sait quand l'appel ajax est effectué dépend de l'implémentation. Il peut être implémenté avec des threads ou il peut également être piloté par l'événement lui-même (cela n'a pas vraiment d'importance). Le point de l'implémentation est que lorsque la réponse ajax est terminée, du code natif saura que c'est fait et mettra un événement dans la file d'attente JS.

Si aucun Javascript n'est en cours d'exécution à ce moment, l'événement sera immédiatement déclenché qui exécutera le gestionnaire de réponse ajax. Si quelque chose est en cours d'exécution à ce moment-là, l'événement sera traité lorsque le thread d'exécution javascript en cours se terminera. Il n'y a pas besoin d'être interrogé par le moteur javascript. Lorsqu'un morceau de Javascript termine son exécution, le moteur JS vérifie simplement la file d'attente des événements pour voir s'il y a autre chose à exécuter. Si tel est le cas, il supprime l'événement suivant de la file d'attente et l'exécute (appelant une ou plusieurs fonctions de rappel enregistrées pour cet événement). Si rien ne se trouve dans la file d'attente d'événements, l'interpréteur JS dispose de temps libre (garbage collection ou inactif) jusqu'à ce qu'un agent externe place autre chose dans la file d'attente d'événements et le réveille à nouveau.

Étant donné que tous les événements extérieurs passent par la file d'attente des événements et qu'aucun événement n'est jamais déclenché pendant que javascript exécute réellement autre chose, il reste à thread unique.

Voici quelques articles sur les détails:

208
jfriend00

Vous pouvez trouver ici une documentation très complète sur la gestion des événements en javascript.
Il est écrit par un gars travaillant sur l'implémentation javascript dans le navigateur Opera.

Plus précisément, regardez les titres: "Event Flow", "Event Queuing" et "Non-user Events": vous apprendrez que:

  1. Javascript s'exécute dans un seul fil pour chaque onglet ou fenêtre de navigateur.
  2. Les événements sont mis en file d'attente et exécutés séquentiellement.
  3. XMLHttpRequest sont exécutés par l'implémentation et les rappels sont exécutés à l'aide de la file d'attente d'événements.

Remarque: Le lien d'origine était: lien , mais il est maintenant mort.

16
qwertzguy

Je voudrais développer un peu, concernant l'implémentation ajax mentionnée dans les réponses.

Bien que l'exécution Javascript (régulière) ne soit pas multithread - comme indiqué dans les réponses ci-dessus - cependant , la gestion réelle du AJAX responses (ainsi que la gestion des requêtes) n'est pas Javascript, et il - généralement - est multi-thread. (voir implémentation de la source de chrome de XMLHttpRequest que nous allons discuter ci-dessus)

et je vais vous expliquer, prenons le code suivant:

var xhr = new XMLHttpRequest();

var t = Date.now;
xhr.open( "GET", "https://swx.cdn.skype.com/shared/v/1.2.15/SkypeBootstrap.min.js?v="+t(), true );

xhr.onload = function( e ) {
                console.log(t() + ': step 3');
    
    alert(this.response.substr(0,20));
};
console.log(t() + ': step 1');
xhr.send();
console.log(t() + ': step 2');

after an AJAX request is made (- après l'étape 1), puis pendant que votre code js s'exécute (étape 2 et suivantes), le navigateur commence le vrai travail de: 1. formatage d'une requête tcp 2. ouverture d'un socket 3. envoi d'en-têtes 4. prise de contact 5 envoi du corps 6. attente de la réponse 7. lecture des en-têtes 8. lecture du corps, etc. par exemple, l'implémentation de chrome mentionnée utilise Threadable Loader go digg-into ????, (vous pouvez également en obtenir impression en regardant l'onglet réseau d'un chargement de page, vous verrez des requêtes simultanées).

en conclusion, je dirais que - au moins - la plupart de vos opérations d'E/S peuvent être effectuées simultanément (et vous pouvez en profiter en utilisant un attendez par exemple). mais toutes les interactions avec ces opérations (l'émission, l'exécution du rappel js) sont toutes synchrones.

0
shmulik friedman