Comprensione di JavaScript sincrono e asincrono - Parte 1
Sincrono e asincrono sono concetti confusi in JavaScript, specialmente per i principianti. Due o più cose sono sincrono quando essi accadere allo stesso tempo (in sincronizzazione), e asincrono quando non lo fanno (non sincronizzato).
Sebbene queste definizioni siano facili da comprendere, in realtà è più complicata di quanto sembri. Dobbiamo tener conto cosa sono esattamente in sincronia, e cosa non lo sono.
Probabilmente chiameresti un normale
funzione in JavaScript sincrono, giusto? E se è qualcosa di simile setTimeout ()
o AJAX con cui stai lavorando, ti riferirai ad esso come asincrono, sì? E se ti dicessi questo tutti e due sono asincroni in un modo?
Per spiegare il perché, dobbiamo rivolgerci al signor X per chiedere aiuto.
Scenario 1 - Il signor X sta provando la sincronicità
Ecco la configurazione:
- Il signor X è qualcuno che può rispondere a domande difficili e svolgere qualsiasi compito richiesto.
- L'unico modo per contattarlo è attraverso una telefonata.
- Qualunque sia la domanda o il compito che hai, per chiedere l'aiuto del signor X a portarlo a termine; tu lo chiami.
- Mr X ti dà la risposta o completa il compito subito, e ti fa sapere E 'fatto.
- Metti giù il ricevitore sentendosi soddisfatto e vai fuori per un film.
Quello che hai appena realizzato era un comunicazione sincrona (avanti e indietro) con il signor X. Ascoltava mentre gli facevi la tua domanda, e ascoltavi mentre rispondeva.
Scenario 2 - Il signor X non è contento della sincronicità
Dal momento che Mr X è così efficiente, inizia a ricevere molte più chiamate. Quindi cosa succede quando lo chiami ma è già occupato parlare con qualcun altro? Non sarai in grado di fargli la tua domanda - non finché non sarà libero di ricevere la tua chiamata. Tutto quello che sentirai è un tono occupato.
Quindi cosa può fare il signor X per combattere questo?
Invece di prendere chiamate direttamente:
- Il signor X assume un nuovo ragazzo, il signor M e gli dà una segreteria telefonica per i chiamanti lasciare messaggi.
- Il lavoro del signor M è quello di passare un messaggio dalla segreteria telefonica al signor X una volta che sa che il signor X ha completamente terminato di elaborare tutti i messaggi precedenti e lo è già libero di prenderne uno nuovo.
- Quindi ora quando lo chiami, invece di ottenere un tono di occupato, devi lasciare un messaggio per Mr X, allora aspetta che ti richiami (non c'è ancora tempo per filmare).
- Una volta che il signor X ha finito con tutti i messaggi in coda che ha ricevuto prima dei tuoi, lui esaminerà il tuo problema, e ti richiamo per darti una risposta.
Ora qui giace la domanda: sono state le azioni finora sincrono o asincrono?
È misto. Quando hai lasciato il tuo messaggio, Mr X non ci stava ascoltando, quindi la quarta comunicazione era asincrona.
Ma quando ha risposto, eri lì ad ascoltare, quale rende la comunicazione di ritorno sincrona.
Spero che tu abbia acquisito una migliore comprensione di come la sincronicità sia percepita in termini di comunicazione. È tempo di inserire JavaScript.
JavaScript - Un linguaggio di programmazione asincrono
Quando qualcuno etichetta JavaScript asincrono, ciò a cui si riferiscono in generale è come puoi lasciate un messaggio per questo, e non hai bloccato la tua chiamata con un tono occupato.
Le chiamate alla funzione sono mai diretto in JavaScript, sono letteralmente fatti via messaggi.
JavaScript utilizza a coda dei messaggi dove vengono trattenuti i messaggi in entrata (o gli eventi). Un evento-loop (un dispatcher di messaggi) invia sequenzialmente tali messaggi a a pila di chiamate dove sono le funzioni corrispondenti dei messaggi impilati come cornici (funzioni e variabili) per l'esecuzione.
Lo stack di chiamate mantiene il frame della funzione iniziale chiamata e ogni altro frame per le funzioni chiamato tramite chiamate annidate sopra .
Quando un messaggio si unisce alla coda, attende fino a quando lo stack di chiamate è vuoto di tutti i frame dal messaggio precedente, e quando lo è, il ciclo degli eventi rimuove il messaggio precedente, e aggiunge i frame corrispondenti del messaggio corrente allo stack di chiamate.
Il messaggio attende di nuovo fino a quando lo stack delle chiamate diventa vuoto dei suoi corrispondenti frame (cioè le esecuzioni di tutte le funzioni impilate sono finite), quindi viene rimossa dalla coda.
Considera il seguente codice:
function foo () function bar () pippo (); function baz () bar (); baz ();
La funzione in esecuzione è baz ()
(nell'ultima riga dello snippet di codice), per cui un messaggio viene aggiunto alla coda, e quando il ciclo di eventi lo preleva, lo stack di chiamate inizia ad impilare i fotogrammi per baz ()
, bar()
, e foo ()
nei punti rilevanti di esecuzione.
Una volta completata l'esecuzione delle funzioni una per una, i loro frame sono rimosso dallo stack di chiamate, mentre il messaggio è ancora in attesa in coda, fino a baz ()
viene estratto dalla pila.
Ricorda, le chiamate alla funzione sono mai diretto in JavaScript, loro sono finiti via messaggi. Quindi, ogni volta che senti qualcuno dire che JavaScript stesso è un linguaggio di programmazione asincrono, supponi che stiano parlando del suo built-in “segreteria telefonica”, e come sei libero di lasciare messaggi.
Ma per quanto riguarda i metodi asincroni specifici?
Finora non ho toccato API come setTimeout ()
e AJAX, quelli sono quelli che sono specificamente indicato come asincrono. Perché?
È importante capire cosa sia esattamente sincrono o asincrono. JavaScript, con l'aiuto di eventi e l'event-loop, può esercitarsi elaborazione asincrona dei messaggi, ma quello non significa qualunque cosa in JavaScript è asincrono.
Ricorda, ti ho detto che il messaggio non è andato via fino a quando lo stack delle chiamate è stato vuoto dei suoi frame corrispondenti, proprio come non te ne sei andato per un film fino a quando non hai ottenuto la tua risposta - è così essere sincrono, sei lì ad aspettare fino a quando l'attività è completa, e ottieni la risposta.
In attesa non è l'ideale in tutti gli scenari. Cosa succede se dopo aver lasciato un messaggio, invece di aspettare, puoi partire per il film? Cosa succede se una funzione può andare in pensione (svuotamento dello stack di chiamate) e il suo messaggio può essere rimosso dalla coda anche prima che l'attività della funzione sia completata? Cosa succede se si può avere codice eseguito in modo asincrono?
Questo è dove API come setTimeout ()
e AJAX entrano in scena e quello che fanno è ... aspetta, non posso spiegarlo senza tornare al signor X, che vedremo nella seconda parte di questo articolo. Rimanete sintonizzati.