Categories
async linguaggio javascript

Linguaggio JavaScript (3)

In questo articolo si vedrà un esempio di funzione asincrona in JavaScript.

I programmi sincroni (come quelli scritti in linguaggio C) sono quelli che svolgono semplicemente un’istruzione dopo l’altra, esattamente come il programmatore le ha scritte nel codice sorgente.
Questi programmi hanno la caratteristica di eseguire una istruzione alla volta, bloccandosi (a volte) senza rispondere alle richieste dell’utente, ad esempio quando incontrano un’istruzione che richiede un tempo lungo per la sua esecuzione (ad esempio, se si chiede di scaricare un file video dalla rete).

Le funzioni che bloccano l’esecuzione dell’intero programma sono dette funzioni bloccanti. Per fare un esempio, le funzioni di I/O sono solitamente bloccanti. Non si bloccano per colpa di un errore o per colpa del programmatore, ma perchè la CPU esegue solitamente un’istruzione alla volta.

Per questo motivo i programmi sincroni sono facili da leggere dall’uomo.

Oggi un’istruzione di tipo bloccante non causa il blocco dell’intero programma perchè i programmatori utilizzano delle tecniche di programmazione concorrente, ossia avviano diverse parti del programma in diversi thread, e fanno eseguire ogni thread in un diverso core della CPU.
La programmazione concorrente non è molto semplice e introduce nuovi problemi da risolvere (ad esempio: risorsa contesa, stallo, ecc.)

I concetti appena descritti sono familiari a chi programma in C++, Java, Python, e molti altri linguaggi simili.

Linguaggi asincroni

Usando il linguaggio JavaScript, invece, l’esecuzione può avvenire nel browser, un ambiente di esecuzione asincrono e come conseguenza le istruzioni possono essere eseguite in un ordine diverso da quello in cui sono state scritte dal programmatore.
In questi casi il programmatore non deve preoccuparsi di gestire l’esecuzione in diversi thread, tuttavia deve cercare di evitare di perdere il controllo sul flusso di esecuzione del programma (mantenere l’ordine delle istruzioni nel programma).

Per questo motivo i programmi JavaScript sono difficili da leggere dall’uomo.


Quando una funzione è detta sincrona?

Quando le istruzioni sono eseguite in ordine, ad esempio nel caso di due diverse righe di codice, quando la prima riga contiene un risultato che deve essere usato nella seconda riga.


In Javascript però, è possibile anche eseguire funzioni asincrone, che cioè si sa quando si avviano, ma non quando ritornano il controllo del flusso (eventualmente ti avvisano quando hanno terminato il loro lavoro).

Esistono diversi metodi per gestire più facilmente le istruzioni asincrone:

  • callback
  • event handler
  • promise
    • metodo then()
    • async/await

Callback

Un metodo di eseguire una funzione dopo l’altra è di chiamare una seconda funzione all’interno della prima funzione (questo sistema è detto callback).

Event handler

Anche un event handler è un tipo di funzione asincrona, nel senso che non sappiamo quando l’evento arriva, e quindi la funzione handler è asincrona.

Per questo motivo un handler si può vedere come una callback, cioè una funzione passata in un’altra funzione, in attesa che la prima termini un compito lungo da svolgere.
In passato tutte le parti asincrone in Javascript erano realizzate tramite Callback, con grossi problemi di leggibilità e di risoluzione dei bug.
Per continuare ad usare le Callback, senza complicare il codice sorgente, si sono introdotte funzioni che restituiscono oggetti Promise, perché sono più facili da usare rispetto alle Callback

Promise

Promise è un tipo di oggetto che momentaneamente è in sospeso (pending) e che in futuro potrebbe diventare di un altro tipo ben determinato (settled):

  • completamento di un’operazione asincrona
  • fallimento di un’operazione asincrona (con errore specificato al momento)

Metodo then()

Dato che siamo spesso dei consumatori di Promise, vediamo prima come si usano. Nel prossimo esempio, funzioneDownload (funzione asincrona) restituirà un oggetto Promise, quindi si potrebbe invocare in questo modo:

funzioneDownload().then(seVaBene,seVaMale)

grazie a then() vengono passate due funzioni Callback

  • seVaBene
  • seVaMale

funzioneDownload restituisce immediatamente il controllo alla riga successiva, restituendo momentaneamente un oggetto Promise. Grazie a then, che possiede due argomenti, all’oggetto Promise si applicheranno due funzioni di callback.

Non è obbligatorio usare then(). Esiste un’alternativa

async e await

Ripetiamo il precedente esempio usando async e await

async function f() {
  try { 
    const risultato = await funzioneDownload();
    if (!risultato) { throw new Error();}
    risultato.seVaBene();
  } catch (errore) {
      seVaMale(); 
    }
}

async e await permettono di usare una funzione asincrona come se fosse sincrona.

Tuttavia usando then è semplice immaginare come eseguirli in cascata (chained then)

funzioneDownload()
.then(seVaBene)
.then(seBene)
.catch(seVaMale)

Ripetiamo il precedente esempio usando async e await

async function f() {
  let risultato;
  try {
    risultato = await funzioneDownload();
  } catch (e) {
    risultato = await seVaMale();
  }
  return seVaBene(risultato);
}

Leave a Reply