From da78a9e329e272dedb2400b79a3bdeebff387d47 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:17 -0500 Subject: initial commit --- files/it/web/javascript/eventloop/index.html | 106 +++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 files/it/web/javascript/eventloop/index.html (limited to 'files/it/web/javascript/eventloop') diff --git a/files/it/web/javascript/eventloop/index.html b/files/it/web/javascript/eventloop/index.html new file mode 100644 index 0000000000..2d68168864 --- /dev/null +++ b/files/it/web/javascript/eventloop/index.html @@ -0,0 +1,106 @@ +--- +title: Modello di parallelismo ed Event Loop +slug: Web/JavaScript/EventLoop +translation_of: Web/JavaScript/EventLoop +--- +
{{JsSidebar("Advanced")}}
+ +
Javascript ha un modello di parallelismo basato su un "event loop". Questo modello è abbastanza differente dai modelli degli altri linguaggi quali, per esempio, C e Java.
+ +
+ +

Runtime

+ +

Questa sezione descrive un modello teorico. I moderni engine JavaScript implementano ed ottimizzano pesantemente la semantica descritta.

+ +

Rappresentazione grafica

+ +

Stack, heap, queue

+ +

Stack

+ +

Chiamate di funzioni da uno stack di frames.

+ +
function f(b){
+  var a = 12;
+  return a+b+35;
+}
+
+function g(x){
+  var m = 4;
+  return f(m*x);
+}
+
+g(21);
+
+ +

Quando viene invocata g, viene creato un primo frame contenente gli argomenti di g e le variabili locali. Quando invoca f, viene creato un secondo frame con un'operazione di push sopra il primo, contenente gli argomenti di f e le variabili locali. Quando esce con il return, viene effettuata un'operazione di pop sullo stack (nel quale rimane quindi solo g). Quando anche g effettua il return, lo stack rimane vuoto.

+ +

Heap

+ +

L'heap indica una grande regione di memoria perlopiù non strutturata.

+ +

Queue

+ +

Un runtime JavaScript contiene una coda(queue) di messaggi, ossia una lista di messaggi da essere processati. Ad ogni messaggio è associata una funzione. Quando lo stack è vuoto, viene estratto un messaggio dalla coda e processato, ossia viene chiamata la funzione associata (e, pertanto, viene creato un frame nello stack). L'elaborazione dei messaggi finisce quando lo stack ritorna ad essere vuoto.

+ +

Event loop

+ +

L'event loop prende il suo nome dalla modalità con cui viene normalmente implementato, ossia tipicamente: 

+ +
while(queue.waitForMessage()){
+  queue.processNextMessage();
+}
+ +

queue.waitForMessage attende che arrivi un messaggio quando non c'e' ne sono.

+ +

"Run-to-completion"

+ +

Ogni messaggio viene completamente elaborato prima di passare ad un altro. Questa dinamica offre alcune comode proprietà quando si ragiona sul proprio programma, incluso il fatto che, fino a che una funzione è in esecuzione, non c'è modo di bloccarla (pre-emption) e completerà la propria esecuzione prima che un altro codice possa essere eseguito (e possa manipolare i dati che la funzione manipola). Questo è completamente diverso dal C, ad esempio, dove, se una funzione è eseguita in un thread, può essere bloccata in qualsiasi momento per eseguire altro codice di un altro thread.   

+ +

Un aspetto negativo di questo modello sta nel fatto che se un messaggio impiega troppo tempo ad essere processato, l'applicazione web non puà elaborare le interazioni dell'utente, come i click o gli scroll. Il browser in qualche modo mitiga questa situazione con la finestra "uno script sta impiegando troppo tempo a completare". Una buona pratica da seguire è di implementare l'elaborazione di un messaggio in modo che impieghi poco tempo e, se possibile, suddividere un messaggio in più messaggi.

+ +

Aggiungere messaggi

+ +

Nei browser web, i messaggi sono continuamente aggiunti ogni qualvolta si verifica un evento con un event listener associato. Quindi il click ad un elemento con un un handler associato aggiungerà un messaggio--così come ogni altro evento.

+ +

Una chiamata alla funzione setTimeout aggiunge un messaggio alla coda dopo che il tempo indicato come secondo argomento è trascorso. Se non c'è nessun altro messaggio nella coda, il messaggio è processato immediatamente; al contrario, se ci sono altri messaggi, il messaggio aggiunto da setTimeout dovrà attendere che gli altri messaggi vengano processati. Per questa ragione il secondo argomento di questa funzione indica un tempo minimo e non un tempo garantito.

+ +

Intervallo zero

+ +

Zero delay non significa in realtà che la funzione di callback verrà attivata dopo zero millisecondi. Una chiamata a {{domxref("WindowTimers.setTimeout", "setTimeout")}} con un delay di 0 (zero) millisecondi, non esegue la funzione di callback dopo l'intervallo di tempo passato. L'esecuzione dipende dal numero di task in attesa nella coda. Nel seguente esempio il messaggio "this is just a message" verrà stampato a console prima che il messaggio della callback venga processato, perchè il ritardo è il minimo tempo richiesto per elaborare la richiesta, non un tempo garantito.

+ +
(function () {
+
+  console.log('this is the start');
+
+  setTimeout(function cb() {
+    console.log('this is a msg from call back');
+  });
+
+  console.log('this is just a message');
+
+  setTimeout(function cb1() {
+    console.log('this is a msg from call back1');
+  }, 0);
+
+  console.log('this is the end');
+
+})();
+
+// "this is the start"
+// "this is just a message"
+// "this is the end"
+// "this is a msg from call back"
+// "this is a msg from call back1"
+
+ +

Più Runtime in comunicazione tra loro

+ +

Un web worker oppure un iframe cross-origin hanno i loro stack, heap e coda di messaggi. Due runtime distinti possono comunicare esclusivamente attraverso il metodo postMessageQuesto metodo aggiunge il messaggio all'altro runtime se quest'ultimo è in ascolo degli eventi dei messaggi.

+ +

Non bloccante

+ +

Una proprietà molto interessante del modello event loop è che JavaScript, a differenza di molti altri linguaggi, non è mai bloccante. La gestione delle operazionei di I/O è tipicamente eseguita mediante eventi e callback, pertanto quando l'applicazione è in attesa che una query  IndexedDB restituisca il risultato oppure una richiesta di tipo XHR completi, può nel frattempo continuare a processare altre cose quali, ad esempio, gli user input.

+ +

Esistono delle eccezioni dovuti alla legacy quali alert oppure le richieste sincrone XHR, ma è considerata una buona pratica evitarle. Attenzione: esistono anche eccezioni alle eccezioni (ma sono solitamente bachi implementativi o altro).

-- cgit v1.2.3-54-g00ecf