In che modo JavaScript gestisce le risposte AJAX in background?


139

Poiché JavaScript viene eseguito in un singolo thread, dopo che è stata effettuata una richiesta AJAX, cosa succede effettivamente in background? Vorrei approfondire questo aspetto, qualcuno può far luce?


6
Una descrizione abbastanza buona è qui: stackoverflow.com/questions/2914161/ajax-multi-threaded
Jonathan M

3
Il codice JavaScript è a thread singolo (eccetto per i web worker), ma non il browser che esegue il motore JavaScript ...
Juan Mendes,

@JuanMendes Il JavaScript viene eseguito in un thread mentre la coda degli eventi viene eseguita in un altro thread?
Shaun Luttin,

1
@ShaunLuttin No, la coda degli eventi è ciò che dà il via a JavaScript
Juan Mendes,

Risposte:


213

Sotto le copertine, JavaScript ha una coda di eventi. Ogni volta che termina un thread di esecuzione javascript, controlla se esiste un altro evento nella coda da elaborare. Se c'è, lo estrae dalla coda e attiva quell'evento (come un clic del mouse, per esempio).

La rete del codice nativo che si trova sotto la chiamata ajax saprà quando la risposta ajax è stata eseguita e un evento verrà aggiunto alla coda degli eventi javascript. Il modo in cui il codice nativo sa quando viene eseguita la chiamata ajax dipende dall'implementazione. Può essere implementato con thread o può anche essere guidato dagli eventi (non importa davvero). Il punto dell'implementazione è che quando viene eseguita la risposta ajax, alcuni codici nativi sapranno che è stato fatto e inseriscono un evento nella coda JS.

Se al momento non è in esecuzione JavaScript, l'evento verrà immediatamente attivato e verrà eseguito il gestore della risposta ajax. Se qualcosa è in esecuzione al momento, l'evento verrà elaborato al termine dell'attuale thread di esecuzione javascript. Non è necessario alcun polling da parte del motore JavaScript. Quando un pezzo di Javascript termina l'esecuzione, il motore JS controlla semplicemente la coda degli eventi per vedere se c'è qualcos'altro che deve essere eseguito. In tal caso, elimina l'evento successivo dalla coda ed esegue (chiamando una o più funzioni di callback registrate per quell'evento). Se nella coda degli eventi non è presente nulla, l'interprete JS ha tempo libero (garbage collection o inattivo) fino a quando un agente esterno inserisce qualcos'altro nella coda degli eventi e lo riattiva.

Poiché tutti gli eventi esterni passano attraverso la coda degli eventi e nessun evento viene mai attivato mentre javascript esegue effettivamente qualcos'altro, rimane a thread singolo.

Ecco alcuni articoli sui dettagli:


Grazie per quello Sospettavo che fosse così, ma è bene saperlo con certezza. Ho un ciclo for, in cui invio molte richieste "ajax". Nel mio gestore (per ogni richiesta - restituito in ordine arbitrario) eseguo del codice che potrebbe richiedere del tempo. Buono a sapersi, questo dovrebbe sicuramente funzionare.
iPadDeveloper2011

4
@telandor: gli eventi vengono eseguiti in ordine FIFO (è possibile che ci siano alcune eccezioni al limite, ma l'intento è FIFO). Alcuni eventi sono trattati in modo leggermente diverso. Ad esempio, gli eventi mousemove non si accumulano nella coda (probabilmente perché potrebbero facilmente traboccare la coda). Quando il mouse si sposta e un evento mousemove è già nella coda e non ci sono altri eventi più recenti nella coda, viene aggiornato con l'ultima posizione anziché un nuovo evento aggiunto. Immagino che anche gli eventi con timer ad intervallo siano trattati in modo speciale per evitare che si accumulino in coda.
jfriend00

2
@telandor - cosa ti serve di più spiegato? È FIFO. Ho aggiunto alcuni altri articoli di riferimento alla mia risposta. Le uniche esecuzioni di FIFO di cui sono a conoscenza sono eventi immediatamente attivati. Si chiama .focus()un elemento e ciò attiva un paio di altri eventi come un evento di "sfocatura" sull'elemento con lo stato attivo. Quell'evento di sfocatura si verifica in modo sincrono e non passa attraverso la coda degli eventi, quindi accadrebbe immediatamente prima di altre cose che potrebbero trovarsi nella coda degli eventi. In pratica, non ho mai trovato questo un problema pratico.
jfriend00

2
@telandor - Non ci sono più code per documento del browser. C'è una coda e tutto va in serie FIFO in / out. Quindi i timeout e le risposte ajax e gli eventi del mouse e gli eventi della tastiera vanno tutti nella stessa coda. Qualunque sia stato messo in coda, viene eseguito per primo.
jfriend00,

1
@CleanCrispCode - Thx. L'ho aggiunto come utile riferimento alla mia risposta.
jfriend00,

16

Puoi trovare qui una documentazione molto completa sulla gestione degli eventi in javascript.
È scritto da un ragazzo che sta lavorando all'implementazione di JavaScript nel browser Opera.

Più precisamente, guarda i titoli: "Flusso di eventi", "Accodamento eventi" e "Eventi non utente": imparerai che:

  1. Javascript viene eseguito in un singolo thread per ciascuna scheda o finestra del browser.
  2. Gli eventi vengono messi in coda ed eseguiti in sequenza.
  3. XMLHttpRequest viene eseguito dall'implementazione e i callback vengono eseguiti utilizzando la coda degli eventi.

Nota: il link originale era: link , ma ora è morto.


1

Voglio elaborare un po ', per quanto riguarda l'implementazione ajax menzionata nelle risposte.

Sebbene l'esecuzione (regolare) di Javascript non sia multi-thread - come notato bene nelle risposte sopra - tuttavia , la gestione reale del AJAX responses(così come la gestione della richiesta) non è Javascript, e - di solito - è multi-thread. (vedi l'implementazione della fonte di cromo di XMLHttpRequest di cui parleremo sopra)

e ti spiego, prendiamo il seguente codice:

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(- dopo il passaggio 1), quindi mentre l'esecuzione del codice js (passaggio 2 e successivi), il browser avvia il vero lavoro di: 1. formattazione di una richiesta tcp 2. apertura di un socket 3. invio di intestazioni 4. handshaking 5. invio body 6. in attesa di risposta 7. lettura delle intestazioni 8. lettura del body ecc. tutta questa implementazione è di solito eseguita in un thread diverso in parallelo all'esecuzione del codice js. per esempio, l'implementazione del cromo menzionata usa Threadable Loader go digg-into 😉, (puoi anche avere qualche impressione guardando la scheda di rete di un caricamento di pagina, vedrai alcune richieste simultanee).

in conclusione, direi che - almeno - la maggior parte delle operazioni di I / O può essere effettuata simultaneamente / asincrona (e puoi approfittarne usando ad esempio un wait ). ma tutte le interazioni con tali operazioni (emissione, esecuzione di callback js) sono tutte sincrone.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.