diff options
Diffstat (limited to 'files/it/web/javascript/eventloop/index.html')
-rw-r--r-- | files/it/web/javascript/eventloop/index.html | 106 |
1 files changed, 106 insertions, 0 deletions
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 +--- +<div>{{JsSidebar("Advanced")}}</div> + +<div>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.</div> + +<div></div> + +<h2 id="Runtime">Runtime</h2> + +<p>Questa sezione descrive un modello teorico. I moderni engine JavaScript implementano ed ottimizzano pesantemente la semantica descritta.</p> + +<h3 id="Rappresentazione_grafica">Rappresentazione grafica</h3> + +<p style="text-align: center;"><img alt="Stack, heap, queue" src="/files/4617/default.svg" style="height: 270px; width: 294px;"></p> + +<h3 id="Stack">Stack</h3> + +<p>Chiamate di funzioni da uno stack di <em>frames</em>.</p> + +<pre class="brush: js">function f(b){ + var a = 12; + return a+b+35; +} + +function g(x){ + var m = 4; + return f(m*x); +} + +g(21); +</pre> + +<p>Quando viene invocata <code>g</code>, viene creato un primo frame contenente gli argomenti di <code>g </code>e le variabili locali. Quando <code>g </code>invoca <code>f, </code>viene creato un secondo frame con un'operazione di push sopra il primo, contenente gli argomenti di <code>f</code> e le variabili locali. Quando <code>f </code>esce con il return, viene effettuata un'operazione di pop sullo stack (nel quale rimane quindi solo <code>g</code>). Quando anche <code>g</code> effettua il return, lo stack rimane vuoto.</p> + +<h3 id="Heap">Heap</h3> + +<p>L'heap indica una grande regione di memoria perlopiù non strutturata.</p> + +<h3 id="Queue">Queue</h3> + +<p>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.</p> + +<h2 id="Event_loop">Event loop</h2> + +<p>L'event loop prende il suo nome dalla modalità con cui viene normalmente implementato, ossia tipicamente: </p> + +<pre class="brush: js">while(queue.waitForMessage()){ + queue.processNextMessage(); +}</pre> + +<p><code>queue.waitForMessage</code> attende che arrivi un messaggio quando non c'e' ne sono.</p> + +<h3 id="Run-to-completion">"Run-to-completion"</h3> + +<p>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. </p> + +<p>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.</p> + +<h3 id="Aggiungere_messaggi">Aggiungere messaggi</h3> + +<p>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.</p> + +<p>Una chiamata alla funzione <code><a href="/en-US/docs/Web/API/WindowTimers.setTimeout">setTimeout</a> </code>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 <code>setTimeout </code>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.</p> + +<h3 id="Intervallo_zero">Intervallo zero</h3> + +<p>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.</p> + +<pre class="brush: js">(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" +</pre> + +<h3 id="Più_Runtime_in_comunicazione_tra_loro">Più Runtime in comunicazione tra loro</h3> + +<p>Un web worker oppure un <code>iframe </code>cross-origin hanno i loro stack, heap e coda di messaggi. Due runtime distinti possono comunicare esclusivamente attraverso il metodo <code><a href="/en-US/docs/DOM/window.postMessage">postMessage</a>. </code>Questo metodo aggiunge il messaggio all'altro runtime se quest'ultimo è in ascolo degli eventi dei messaggi.</p> + +<h2 id="Non_bloccante">Non bloccante</h2> + +<p>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 <a href="/en-US/docs/Web/API/IndexedDB_API">IndexedDB</a> restituisca il risultato oppure una richiesta di tipo <a href="/en-US/docs/Web/API/XMLHttpRequest">XHR</a> completi, può nel frattempo continuare a processare altre cose quali, ad esempio, gli user input.</p> + +<p>Esistono delle eccezioni dovuti alla legacy quali <code>alert </code>oppure le richieste sincrone XHR, ma è considerata una buona pratica evitarle. Attenzione: esistono anche <a href="http://stackoverflow.com/questions/2734025/is-javascript-guaranteed-to-be-single-threaded/2734311#2734311">eccezioni alle eccezioni</a> (ma sono solitamente bachi implementativi o altro).</p> |