Nella prima parte di questo tutorial, abbiamo appreso i principi alla base della programmazione asincrona e l'utilizzo di callback. Per verificare, la programmazione asincrona ci consente di scrivere codice che non è bloccante eseguendo successivamente attività di blocco. Le funzioni di callback forniscono un modo per sincronizzare l'esecuzione del nostro codice.
Tuttavia, la ripetizione di callback ripetutamente non è un buon esempio da seguire. Ecco le promesse in soccorso. Le promesse sono state utilizzate per un po 'nelle librerie JavaScript, ma ora puoi usarle in modo nativo nel tuo codice. Le funzioni asincrone migliorano le promesse permettendoci di scrivere i nostri compiti uno dopo l'altro senza che ci dobbiamo preoccupare dei tempi della loro esecuzione.
Diamo un'occhiata a ciò che una promessa è concettualmente. Immagina lo scenario in cui acquisti online e acquisti un paio di scarpe. Al momento del check-out, ti verrà inviato via email un riepilogo del tuo acquisto.
Questa conferma d'ordine è come una promessa. La promessa è la tua garanzia che otterrai qualcosa in seguito dalla società. Mentre il tuo ordine è in sospeso, la tua vita non si ferma, ovviamente. Continui a svolgere altre attività come navigare su Internet. Se il tuo ordine è soddisfatto, riceverai un'email con le informazioni di spedizione. È possibile che il tuo ordine venga rifiutato. L'articolo che hai ordinato potrebbe essere esaurito o potrebbe esserci un problema con il tuo metodo di pagamento. In questo caso, riceverai un'email che ti informa dell'errore.
Nel codice parla, una promessa è un oggetto che assicura che otterremo un valore futuro per la nostra richiesta, sia che abbia esito positivo sia che non riesca. Questa è la forma generale per creare e utilizzare una promessa:
function task1 () return new Promise (function (resolve, reject) resolve (data); reject (errore);); task1 () .then (function (result) console.log (result);) .catch (function (error) console.log (errore););
Per creare una promessa, istanziate un oggetto promessa e scrivete il vostro codice asincrono all'interno della funzione di callback della promessa. I dati che vuoi restituiti dalla promessa vengono passati come argomento al risolvere
funzione, e il tuo messaggio di errore è passato nel rifiutare
funzione. Mettiamo insieme le promesse usando il poi
metodo. Questo ci permette di eseguire i compiti in sequenza.
Se dobbiamo passare i risultati di un'attività alla prossima attività, la restituiamo nel poi
metodo. Potremmo voler mettere insieme le promesse quando siamo interessati alla trasformazione dei valori o dobbiamo eseguire il nostro codice in un ordine particolare. Alla fine della catena, prendiamo i nostri errori. Se si verifica un errore in una delle nostre attività, le attività rimanenti vengono saltate e l'errore viene inviato al nostro blocco catch.
Nella prima parte di questo tutorial, abbiamo usato i callback per aprire un file e recuperare un post e i suoi commenti. Ecco come appare il codice completo usando le promesse:
const fs = require ('fs'); const path = require ('path'); const postsUrl = path.join (__ dirname, 'db / posts.json'); const commentsUrl = path.join (__ dirname, 'db / comments.json'); // restituisce i dati dalla nostra funzione file loadCollection (url) return new Promise (function (resolve, reject) fs.readFile (url, 'utf8', function (error, data) if (error) reject (' errore '); else resolve (JSON.parse (data)););); // restituisce un oggetto dalla funzione id getRecord (collection, id) return new Promise (function (resolve, reject) const data = collection.find (function (element) return element.id == id;); risolvere (dati);); // restituisce una matrice di commenti per una funzione post getCommentsByPost (commenti, postId) return comments.filter (function (comment) return comment.postId == postId;); // codice di inizializzazione loadCollection (postsUrl) .then (function (posts) return getRecord (posts, "001");) .then (function (post) console.log (post); return loadCollection (commentsUrl); ) .then (function (comments) const postComments = getCommentsByPost (commenti, "001"); console.log (postComments);) .catch (funzione (errore) console.log (errore););
La differenza qui è che il nostro metodo per aprire il file è ora avvolto in un oggetto promessa. E invece di annidare i nostri compiti con i callback, sono concatenati insieme a poi
.
Come puoi vedere, non abbiamo eliminato la necessità di richiamare. Li stiamo solo utilizzando in modo diverso. Prima, abbiamo annidato i nostri callback in modo da poter continuare l'esecuzione del nostro codice nella prossima attività.
Questo mi ricorda quando chiamo il servizio clienti per un problema e invece che l'agente risolve il mio problema, vengo trasferito a qualcun altro. Che qualcun altro possa o meno risolvere la chiamata, ma per quanto riguarda il primo agente, è responsabilità di qualcun altro.
Con le promesse, otterremo qualcosa prima di passare al prossimo compito. Se dobbiamo portare quel qualcosa alla prossima continuazione del nostro codice, possiamo usare a poi
dichiarazione.
Usando le promesse, scrivi un programma che aprirà un file di utenti, ottieni le informazioni dell'utente, quindi apri un file di post e stampa tutti i post dell'utente.
Le promesse sono un miglioramento nel design del nostro programma, ma possiamo fare di meglio. Sarebbe molto comodo se potessimo eseguire i nostri compiti in modo sincrono come questo:
task1 (); TASK2 (); TASK3 ();
Bene, possiamo farlo con lo schema asincrono / atteso. Per fare ciò, iniziamo avvolgendo le nostre attività in una funzione asincrona. Questa funzione restituisce una promessa. Quindi implementiamo la gestione degli errori avvolgendo le nostre attività all'interno di a prova a prendere
dichiarazione.
Se la promessa è soddisfatta, completerà qualsiasi compito fosse all'interno del nostro provare
bloccare. Se è respinto, il catturare
il blocco verrà eseguito. Aggiungere il attendere
parola chiave prima di qualsiasi attività sospende il nostro programma fino al completamento dell'attività.
Questa è la forma generale per utilizzare le funzioni asincrone:
funzione async initTasks () try const a = attende task1 (); const b = attende task2 (); const c = attende task3 (); // fai qualcosa con a, b, e c catch (error) // fai qualcosa con l'oggetto error initTasks ();
Usando questo modello, possiamo riscrivere come eseguiamo il nostro codice nel nostro esempio di file.
funzione asincrona getPost () try const posts = attende loadCollection (postsUrl); const post = attende getRecord (post, "001"); const comments = attende loadCollection (commentsUrl); const postComments = attendi getCommentsByPost (commenti, post.id); console.log (post); console.log (postComments); catch (errore) console.log (errore); getPost ();
Mi piace strutturare il nostro codice asincrono con a prova a prendere
dichiarazione perché separa nettamente il codice di gestione degli errori dal codice normale. Se qualcuno del codice nel nostro provare
il blocco causa un errore, sarà gestito dal catturare
bloccare. Inoltre, possiamo aggiungere un finalmente
blocco che eseguirà il codice indipendentemente dal fatto che i nostri compiti abbiano esito positivo o negativo.
Un esempio per l'utilizzo di questo modello è quando abbiamo il codice di pulizia che dobbiamo eseguire. Questo codice non deve necessariamente essere contenuto in a finalmente
bloccare. Può essere scritto dopo il catturare
dichiarazione, e verrà eseguita. Le promesse non hanno questa sintassi incorporata. Dovremmo incatenare un'altra poi
dichiarazione dopo la nostra catturare
dichiarazione per ottenere lo stesso effetto.
Usando async / await, scrivi un programma che aprirà un file di utenti, ottieni le informazioni dell'utente, quindi apri un file di post e stampa le informazioni dell'utente e tutti i loro post.
Le callback non sono intrinsecamente malvagie. Passare le funzioni in altre funzioni è un utile schema in JavaScript. Le callback diventano un problema quando le usiamo per controllare il flusso della nostra logica applicativa. Poiché JavaScript è asincrono, dobbiamo fare attenzione a come scriviamo il nostro codice perché le attività non necessariamente finiranno nell'ordine in cui sono state scritte. Non è una cosa negativa perché non vogliamo alcun compito che blocchi la continuazione del programma.
Le promesse sono un modello migliore per scrivere codice asincrono. Non risolvono solo il disordine dei callback nidificati, ma mantengono anche il controllo del risultato di un'attività all'interno dell'attività. Il passaggio del controllo a un'altra attività, indipendentemente dal fatto che tale attività sia il nostro codice o un'API di terze parti, rende il nostro codice meno affidabile. Infine, le funzioni asincrone ci permettono di scrivere il nostro codice in modo sincrono, che è molto più intuitivo e più facile da capire.