2012-04-03 20 views
10

Supponiamo che io sono un gestore di eventi che rende due chiamate AJAX al server:I gestori di eventi sono garantiti per il completamento prima che vengano richiamati i callback AJAX?

$("#foo").click(function(){ 
    $.get("bar", function(){ alert("Hello"); }); 
    $.get("baz", function(){ alert("World"); }); 
}); 

mi rendo conto che l'ordine in cui vengono chiamati i callback è non deterministico, in quanto dipende da quanto tempo ogni richiesta prende, etc.

Ma ecco la mia domanda: è garantito che raggiungerò la fine del mio gestore di eventi prima che venga richiamata una delle funzioni di callback? Ho letto che tutto il Javascript per una pagina viene eseguito in un singolo thread, quindi penso che ciò implichi che il mio gestore di eventi click sia garantito per essere completato prima di poter richiamare qualsiasi callback.

È corretto? O è possibile che la prima richiesta sia completa E la prima callback eseguita prima che arriviamo alla fine del nostro gestore di eventi?

risposta

10

Sì, questo è garantito e hai ragione - c'è solo un singolo thread (ignorando s per il momento). Quando un pezzo di codice JavaScript viene eseguito (occupa il thread di esecuzione) e arriva un callback AJAX (o qualsiasi altro evento della GUI, timeout, ecc.) Viene accodato e attende fino a quando il thread di esecuzione è libero (la parte di codice corrente finisce).

Il motore JavaScript non interromperà mai il codice in esecuzione per gestire l'evento in arrivo: gli eventi attenderanno sempre delicatamente in coda. Questo è il motivo per cui la GUI sembra bloccarsi quando il codice ad alta intensità di CPU è in esecuzione - nessun evento viene gestito. Anche questo è il motivo per cui le richieste sincrone AJAX sono cattive.

Vedi anche

4

Sì, JavaScript è a thread singolo, quindi l'esecuzione non verrà mai anticipata.

Le richiamate e gli eventi asincroni funzionano allo stesso modo; il tuo gestore per mousedown ha la garanzia di finire prima del gestore per un mouseup, anche se il tuo gestore di mousedown impiega 2 secondi e lasci andare immediatamente il mouse.

Lo stesso vale per un callback AJAX, che viene messo nella stessa coda (tipo di) come eventi in attesa di elaborazione

0

mi rendo conto che l'ordine in cui vengono chiamati i callback è non deterministico, dal momento che dipende da quanto dura ogni richiesta, ecc.

Nel modo in cui lo hai scritto sì .. ma ci sono modi per organizzare e controllare questo .. vale a dire deffereds e promises.

Ecco una buona visione: http://net.tutsplus.com/tutorials/javascript-ajax/wrangle-async-tasks-with-jquery-promises/

L'uso corretto di loro farà in modo che non vi imbatterete in qualsiasi problema ti sembra di essere cercando di evitare.

** Come ha sottolineato @Juan, questa non è la risposta in bianco e nero per la domanda che hai chiesto. Sto solo cercando di indicarti direzioni o modi diversi di guardare allo stesso problema in modo da poter definire il comportamento atteso in modo più esplicito.

+1

L'OP non sta chiedendo informazioni su compiti asincroni che ritornano fuori ordine –

+0

No, non lo è, ma sto dicendo che se controlla tutte le sue chiamate asincrone che probabilmente non incontrerà il problema che sta cercando di evitare nel primo posto. Il che sembra essere quello di assicurarsi che un conduttore termini prima degli altri handler. –

+0

"È corretto? O è possibile che la prima richiesta sia completa E la prima callback eseguita prima che arriviamo alla fine del nostro gestore di eventi?" Se è programmato in un modo che lo rende esplicito, di quanto non avrebbe questa domanda, vero? –

1

Una svolta interessante a questo sarebbe invece di $ .get(), diciamo che stavamo usando le promesse che otteniamo da qualcos'altro (cioè la chiamata asincrona effettiva è stata fatta altrove) (-Perché avremmo una tale situazione ? Beh, forse abbiamo una funzione di query memorizzata.)

Ora, se si usassero le promesse di jQuery, i callback verrebbero richiamati in modo sincrono se già risolti. È mai stato un problema? Bene dipende dal vostro requisito In tal caso, è possibile inserire il codice di richiamata in un setTimeout (cb, 0).

D'altra parte, cosa succede se si desidera che le richiamate vengano anticipate? Vedi my examples here

+0

@Juan Mendes, potrei essere accusato di non rispondere davvero alla domanda troppo :-( –

Problemi correlati