Attendi che una funzione finisca in JavaScript
-
Sync
eAsync
in JavaScript -
Usa
callback
per aspettare che una funzione finisca in JavaScript -
Usa le
promises
per aspettare che una funzione finisca in JavaScript -
Usa
async/await
per attendere che una funzione finisca prima di continuare l’esecuzione
Questo tutorial introdurrà JavaScript Callbacks
, Promises
e Async/await
e ti mostrerà come attendere il termine di una funzione asincrona prima di continuare l’esecuzione.
Per capire cosa sono Promises
e Async/await
, dobbiamo prima capire quali sono le funzioni Sync
e Async
in JavaScript.
Sync
e Async
in JavaScript
La programmazione sincrona esegue un comando alla volta. Quando chiamiamo una funzione che esegue un’azione di lunga durata, interromperà il programma fino al termine.
JavaScript è tradizionalmente a thread singolo, anche con multi-core. Possiamo far sì che esegua attività solo su un singolo thread chiamato thread principale.
Tale comportamento sincrono è un fattore limitante nei multi-thread ma aiuta l’utente a scrivere codici senza preoccuparsi dei problemi di concorrenza.
Durante la programmazione asincrona, l’azione a esecuzione prolungata verrà eseguita in un altro thread diverso dal thread principale, quindi l’esecuzione principale non viene bloccata. Quando quella funzione di lunga durata termina, il programma principale viene informato e ottiene l’accesso ai risultati.
La maggior parte delle primitive di I/O in JavaScript non sono bloccanti. Le richieste di rete, le operazioni sui file system sono tutte operazioni non bloccanti. Il blocco è l’eccezione in JavaScript.
Poiché JavaScript è basato su tecniche di programmazione asincrona, ci sono più approcci come callbacks
, promises
e async/await
che ti consentono di mettere in sequenza le esecuzioni delle tue funzioni. In modo che un blocco di codice o una funzione non vengano eseguiti prima del termine di un’altra funzione specifica.
La figura sopra mostra la netta variazione tra l’esecuzione asincrona e sincrona di due funzioni.
Usa callback
per aspettare che una funzione finisca in JavaScript
Se abbiamo istruzioni sincrone, eseguire queste istruzioni l’una dopo l’altra è semplice.
function one() {
console.log('I am function One');
}
function Two() {
console.log('I am function Two');
}
one();
Two();
Produzione:
I am function One
I am function Two
Supponiamo di voler eseguire due funzioni, functionOne()
e functionTwo()
in modo tale che functionOne()
debba essere eseguita dopo aver eseguito alcune istruzioni asincrone all’interno di functionTwo()
.
function functionOne(_callback) {
// do some asynchronus work
_callback();
}
function functionTwo() {
// do some asynchronus work
functionOne(() => {
console.log('I am a callback');
});
}
functionTwo();
Quando si esegue il codice di cui sopra, l’ultima cosa stampata nella console è I am a callback
. Il famoso esempio di callback
è la funzione setTimeout
con una funzione handler da eseguire dopo il timeout.
function testCallBack() {
console.log('log before use setTimeout function');
setTimeout(() => {
console.log('inside timeout');
}, 5000);
console.log('log after use setTimeout function');
}
testCallBack();
Produzione:
log before use setTimeout function
log after use setTimeout function
inside timeout
Usa le promises
per aspettare che una funzione finisca in JavaScript
Una Promises
è un oggetto che rappresenta l’eventuale adempimento o fallimento di un’operazione asincrona. Alleghiamo il callback di adempimento alla Promises
con una o più istruzioni then
, e when può chiamare il callback del gestore degli errori nel catch
.
doFirstThing()
.then(result => doSecondThing(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log('The final result thing' + finalResult);
})
.catch(failureCallbackfunction);
}
Incatenare le dichiarazioni then
e catch
come nell’esempio precedente è uno dei vantaggi delle promesse. Promettiamo di fare doSecondThing(result)
una volta che doFirstThing()
è soddisfatto. Gli argomenti del then
sono opzionali, ma obbligatori se devi restituire un risultato.
In caso di errore, il browser cercherà il catch
alla fine della catena e lo eseguirà. È molto simile al famoso try-catch
.
Il seguente esempio ci aiuterà a capire le catene delle promises
e ci mostrerà come possiamo aspettare che una funzione con comportamento asincrono termini l’esecuzione prima di poter continuare l’esecuzione.
var resolvedFlag = true;
let mypromise = function functionOne(testInput) {
console.log('Entered function');
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Inside the promise');
if (resolvedFlag == true) {
resolve('Resolved');
} else {
reject('Rejected')
}
}, 2000);
});
};
mypromise()
.then((res) => {console.log(`The function recieved with value ${res}`)})
.catch((error) => {
console.log(`Handling error as we received ${error}`);
});
Produzione:
Entered function
Inside the promise
The function received with value Resolved
Creare una promessa può essere facile come restituire una nuova Promise()
. Il costruttore Promise()
riceve una funzione come argomento, che dovrebbe avere due parametri: resolve
e reject
.
Nel caso in cui il nostro evento sia soddisfatto e abbiamo bisogno di restituire il risultato, usiamo la funzione resolve()
quando riusciamo in quello che stavamo facendo. Ma se si verifica un errore e deve essere gestito, usiamo reject()
per inviare l’errore al catch
.
Impostiamo il flag resolvedFlag = true
per simulare la gestione degli errori nel catch
. Se resolvedFlag
è impostato su false
, viene chiamata la funzione reject()
e l’errore viene gestito nel blocco catch
.
Produzione:
Entered function
Inside the promise
Handling error as we received Rejected
Usa async/await
per attendere che una funzione finisca prima di continuare l’esecuzione
Un altro modo per attendere l’esecuzione di una funzione prima di continuare l’esecuzione nell’ambiente asincrono in JavaScript è usare async/wait
.
La funzione async
è la funzione dichiarata dalla parola chiave async
, mentre all’interno della funzione async
è consentita solo la parola chiave await
e utilizzata per sospendere l’avanzamento all’interno della funzione async fino all’operazione asincrona basata sulla promessa è soddisfatto o rifiutato.
Le parole chiave async
e await
consentono un comportamento asincrono basato sulle promesse in uno stile più pulito.
Capiamo come funziona async/await
. La funzione che stiamo aspettando dovrebbe restituire un’istanza della classe Promise per attendere che venga eseguita utilizzando la parola chiave await prima di chiamarla. Come accennato in precedenza, la funzione che contiene l’istruzione await
deve essere dichiarata con l’istruzione async
.
L’esempio seguente mostra come attendere che la funzione basata sulla promessa finisca prima di continuare l’esecuzione.
function testAsync() {
return new Promise((resolve, reject) => {
// here our function should be implemented
setTimeout(() => {
console.log('Hello from inside the testAsync function');
resolve();
;
}, 5000);
});
}
async function callerFun() {
console.log('Caller');
await testAsync();
console.log('After waiting');
}
callerFun();
Produzione:
Caller
Hello from inside the testAsync function
After waiting