In che modo Javascript è single threaded?

Ho una domanda sulla natura single-threaded di Javascript.

console.log("1"); setTimeout(function(){console.log("2");},3000); console.log("3"); setTimeout(function(){console.log("4");},1000); 

Il risultato di questo codice è 1 3 4 2 . Come vedi, 4 viene dopo 2 che mi fa pensare che in un singolo ambiente thread non dovrebbero venire 2 dopo 4 ? Se no, allora come mai JS sa che il secondo setTimeout dovrebbe finire prima del primo? Non dovrebbero esserci due thread che funzionano contemporaneamente per completare i due setTimeout s per notificare EventLoop ?

JavaScript (nei browser) non viene eseguito contemporaneamente 2 .

Al massimo uno dei callback setTimeout può essere eseguito alla volta, poiché esiste un contesto di esecuzione JavaScript o “thread”.

Tuttavia, il “prossimo timeout pianificato” da eseguire viene sempre eseguito .. successivo. Il “4” viene eseguito prima del callback “2” perché era programmato per essere eseguito prima . I timeout erano pianificati in modo efficace dallo stesso momento (nessuna delle operazioni stava bloccando), ma “2” aveva un intervallo molto più lungo.

L’implementazione sottostante può utilizzare i thread 1 , ma JavaScript nello stesso contesto globale non viene eseguito contemporaneamente e garantisce un comportamento coerente e atomico tra tutti i callback.


1 O potrebbe non; questo può essere gestito senza fili in un’implementazione di select/poll .

2 Nello stesso contesto: vale a dire Tab / Window, WebWorker, controllo browser host. Ad esempio, mentre i WebWorkers vengono eseguiti contemporaneamente, lo fanno in diversi contesti e seguono lo stesso modello asincrono (ad esempio, come usato dai timer).

Javascript esegue ogni riga in sequenza.

Quindi hai detto a js:

  • scrivi 1: js writes 1
  • attendi 3 secondi e poi scrivi 2: ok I'll wait 3 seconds...now what?
  • scrivi 3: ok I'll write 3, by the way, the 3 seconds is not up.
  • aspetta 1 secondo e poi scrivi 4: ok I'll wait 1 second...

quindi js attende .99999 secondi … e scrive 4

poi aspetta ancora e scrive 2

Javascript usa qualcosa chiamato Eventloop per le chiamate asincrone. Il setTimeout viene inviato a EventLoop poiché è un callback. e il thread principale continua ad essere eseguito. Una volta completato il main, Then EventToop spinge i dati nello stack principale. Ex:

 console.log("1"); setTimeout(function(){console.log("2");},0); console.log("3"); setTimeout(function(){console.log("4");},1000); 

Quando il timeout è 0, l’output del codice sarà,

1 3 2 4

Dal momento che esegue prima le chiamate del Main e quindi riporta i dati dal modello Concurrency di Eventloop e dal Loop degli eventi

il secondo parametro di setTimeout richiede il tempo minimo dopo il quale la funzione di callback (primo argomento) deve essere inserita nel ciclo degli eventi, che non è altro che una coda per le funzioni di callback. Questa coda viene utilizzata per avviare effettivamente l’esecuzione.

Una volta che si incontra il primo setTimeout, la funzione viene spinta su un posto esterno e gli viene detto di attendere 3 secondi prima di rientrare nel mondo a thread singolo. Lo stesso accade per la seconda funzione di timeout, ma deve aspettare solo 1 sec. Il punto di ingresso a questo mondo a thread singolo è la coda di callback. JS Engine continua la normale esecuzione come se l’esecuzione di settimeout fosse terminata. Ora alla scadenza di 1 secondo, la funzione del secondo timeout viene inserita nella coda e in attesa di essere eseguita. Se lo stack di chiamate è chiaro in quel punto, la funzione va elaborata (supponendo che fosse il primo membro della coda) e “4” sia stampato. Ora se 3 secondi non sono passati in questo momento, la funzione del primo timeout è ancora in attesa da qualche parte all’esterno. Trascorsi 3 secondi, la funzione di callback entra in coda e, poiché lo stack di chiamate è libero, viene eseguito e viene stampato “2”.

Ora il browser ha accesso a più thread dal sistema operativo (pur fornendo solo un singolo ambiente thread per l’esecuzione di JS). Questi setTimeout vengono elaborati da un altro thread dietro la scena.

C’è un video di Philips Robert che spiega in modo bello i concetti di coda e ciclo degli eventi che conducono all ‘”asincrona” del javascript a thread singolo.

https://www.youtube.com/watch?v=8aGhZQkoFbQ