Asincronia

Frontend SELF IT
Livello 43 , Lezione 0
Disponibile

1.1 Concetti di base dell'asincronia

L'asincronia in JavaScript permette di eseguire attività in background, senza bloccare il flusso principale di esecuzione. Questo è particolarmente importante per compiti che potrebbero richiedere tempo significativo, come richieste di rete, lettura di file e timer. Ora daremo un'occhiata ai concetti di base della programmazione asincrona in JavaScript e forniremo esempi di utilizzo.

Natura single-thread di JavaScript

JavaScript è un linguaggio single-thread: ciò significa che esegue il codice in modo sequenziale su un singolo thread. Tuttavia, le operazioni asincrone permettono di eseguire compiti in background, liberando il flusso principale per altre attività.

Event Loop (Ciclo degli eventi)

Il ciclo degli eventi (Event Loop) è il meccanismo chiave che permette a JavaScript di gestire compiti asincroni. L'Event Loop gestisce la coda dei messaggi (Message Queue) e la coda delle microtasks (Microtask Queue), garantendo l'esecuzione delle operazioni asincrone.

  1. Coda dei messaggi: contiene compiti come gestori di eventi, richieste di rete e timer. I compiti di questa coda vengono eseguiti in sequenza.
  2. Coda delle microtasks: contiene compiti con priorità superiore rispetto a quelli nella coda dei messaggi. Gli esempi includono il completamento dei promises e le chiamate alle funzioni di callback nelle microtasks.

L'Event Loop controlla costantemente entrambe le code ed esegue i compiti da esse, quando il flusso principale diventa libero.

Operazioni asincrone

Le operazioni asincrone permettono di eseguire compiti in background. Gli esempi principali di operazioni asincrone includono:

  • Timer (setTimeout, setInterval)
  • Gestori di eventi
  • Richieste di rete (es., XMLHttpRequest, Fetch API)
  • Lettura/scrittura file (in Node.js)

Diamo un'occhiata ad alcuni esempi di operazioni asincrone.

1.2 Timer

I timer permettono di eseguire compiti con un ritardo o a intervalli regolari di tempo.

Esempio di utilizzo di setTimeout

In questo esempio setTimeout imposta l'esecuzione di una funzione dopo 2 secondi. Come risultato, prima viene stampato Start e End, e poi dopo 2 secondi viene stampato Executed after 2 seconds.

JavaScript
    
      console.log('Start');

      setTimeout(() => {
        console.log('Executed after 2 seconds');
      }, 2000);

      console.log('End');
    
  

Esempio di utilizzo di setInterval

In questo esempio setInterval esegue una funzione ogni secondo, incrementando il contatore e stampandone il valore. Quando il contatore raggiunge 5, l'intervallo viene pulito usando clearInterval:

JavaScript
    
      let counter = 0;

      const intervalID = setInterval(() => {
        counter++;
        console.log(`Counter: ${counter}`);
        if (counter >= 5) {
          clearInterval(intervalID);
        }
      }, 1000);
    
  

1.3 Gestori di eventi

I gestori di eventi permettono di eseguire codice in risposta ad azioni dell'utente o altri eventi.

Esempio di utilizzo di gestori di eventi

In questo esempio, un gestore dell'evento click viene aggiunto a un bottone. Quando l'utente clicca sul bottone, viene stampato il messaggio Button clicked!:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Event Handler Example</title>
        </head>
        <body>
          <button id="myButton">Click me</button>

          <script>
            const button = document.getElementById('myButton');

            button.addEventListener('click', () => {
              console.log('Button clicked!');
            });
          </script>
        </body>
      </html>
    
  

1.4 Richieste di rete

Le richieste di rete permettono di eseguire richieste HTTP asincrone al server.

Esempio di utilizzo di XMLHttpRequest

In questo esempio viene creato un GET request asincrono a un API, e quando la richiesta è completata, la risposta viene stampata in console:

JavaScript
    
      const xhr = new XMLHttpRequest();
      xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', true);

      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
          const response = JSON.parse(xhr.responseText);
          console.log(response);
        }
      };

      xhr.send();
    
  

1.5 Event Loop in azione

Per capire meglio come funziona l'Event Loop, diamo un'occhiata al seguente esempio:

JavaScript
    
      console.log('Start');

      setTimeout(() => {
        console.log('Timeout 1');
      }, 0);

      Promise.resolve().then(() => {
        console.log('Promise 1');
      });

      setTimeout(() => {
        console.log('Timeout 2');
      }, 0);

      Promise.resolve().then(() => {
        console.log('Promise 2');
      });

      console.log('End');
    
  

Il risultato atteso sarà il seguente:

  • Start
  • End
  • Promise 1
  • Promise 2
  • Timeout 1
  • Timeout 2

In questo esempio vengono eseguite prima le operazioni sincrone (console.log('Start') e console.log('End')). Poi vengono eseguite le microtasks (gestori dei promises), e solo dopo vengono eseguiti i compiti dalla coda dei messaggi (setTimeout).

Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION