Mantenere le promesse con JavaScript

JavaScript, attraverso la sua popolarità e i recenti miglioramenti, sta diventando sempre più il migliore amico del programmatore web. E come tutti i migliori amici, JavaScript mantiene le sue promesse. 

Ora può sembrare un po 'strano, ma è vero. La maggior parte dei browser attuali supporta ciò che viene chiamato l'oggetto Promise. Una promessa è quasi come una funzione in quanto rappresenta un pezzo di codice o un'attività che vorresti essere eseguita ad un certo punto nel futuro.

Ecco come appare una promessa.

var myPromise = new Promise (function (resolve, reject) // L'attività da svolgere va qui.);

Potete vedere qui che quando creiamo una promessa, gli diamo un singolo argomento, che è una funzione che contiene il codice che vorremmo eseguire in futuro. Potresti aver notato anche che i due argomenti nella funzione sono passati alla promessa, risolvere e rifiutare. Queste sono anche funzioni e sono il nostro modo di dire alla Promessa se ha fatto ciò che ha promesso di fare. Questo è il modo in cui li useresti:

var myPromise = new Promise (function (resolve, reject) if (true) resolve ('Hello Tuts + fan!'); else reject ('Aww, didn \' t work. '););

Ovviamente questa promessa si risolverà sempre come Se la dichiarazione sarà sempre vera. Questo è solo per scopi di apprendimento - faremo qualcosa di più realistico in seguito - ma immaginiamo di sostituire il vero con uno snippet di codice che non eri sicuro al 100% avrebbe funzionato.

Ora che abbiamo creato una promessa, come la usiamo? Bene, dobbiamo dirgli cosa sono quelli risolvere e rifiutare le funzioni sono. Lo facciamo usando le promesse poi metodo.

myPromise.then (function (result) // Risolvi callback console.log (risultato);, function (result) // Reject callback. console.error (result););

Perché la nostra dichiarazione if sta sempre passando vero controllare, il codice sopra accederà sempre "Ciao Tuts + fan!" alla console. Lo farà anche immediatamente. Questo perché il codice all'interno del costruttore di Promise è sincrono, il che significa che non è in attesa di alcuna operazione da eseguire. Ha tutte le informazioni necessarie per continuare e lo fa il prima possibile. 

Dove le promesse brillano davvero, però, è quando si tratta di compiti asincroni - compiti in cui non si sa quando esattamente la promessa sarà soddisfatta. Un esempio reale di un'attività asincrona è il recupero di una risorsa, ad esempio un file JSON, tramite AJAX. Non sappiamo quanto tempo impiegherà il server per rispondere e potrebbe anche non riuscire. Aggiungiamo alcuni AJAX al nostro codice di promessa.

var myPromise = new Promise (function (resolve, reject) // Richiesta e caricamento della richiesta AJAX standard var request = new XMLHttpRequest (); // Richiedi un commento dell'utente dal nostro blog fasullo. request.open ('GET', ' http://jsonplaceholder.typicode.com/posts/1 '); // Imposta la funzione da chiamare quando viene caricata la risorsa. request.onload = function () if (request.status === 200) resolve (request. risposta); else reject ('Pagina caricata, ma lo stato non è OK.');; // Imposta la funzione da chiamare quando il caricamento non riesce. request.onerror = function () reject ('Aww, didn \' t funziona affatto. '); request.send (););

Il codice qui è solo JavaScript standard per l'esecuzione di una richiesta AJAX. Richiediamo una risorsa, in questo caso un file JSON a un URL specificato, e attendi che risponda. Non sapremo mai esattamente quando. E ovviamente non vogliamo fermare l'esecuzione del copione per aspettarlo, quindi cosa facciamo? 

Bene, fortunatamente abbiamo inserito questo codice in una promessa. Mettendola qui, fondamentalmente stiamo dicendo: "Ehi, pezzo di codice, devo andare proprio ora ma ti chiamerò più tardi e ti dirò quando eseguirlo. Prometti che lo farai e dimmi quando hai fatto?" E il codice dirà: "Sì, certo. Lo prometto". 

Una cosa importante da notare nel suddetto pezzo di codice è la chiamata del risolvere e rifiutare funzioni. Ricorda, questi sono il nostro modo di dire la nostra promessa che il nostro codice ha o non è stato eseguito con successo. Altrimenti, non lo sapremo mai.

Usando lo stesso codice del nostro esempio di base, possiamo vedere come funzionerà ora la nostra richiesta AJAX all'interno della promessa.

// Dì alla nostra promessa di eseguire il suo codice // e dicci quando è finito. myPromise.then (function (result) // Stampa JSON ricevuto sulla console console.log (risultato);, funzione (risultato) // Stampa "Aww non ha funzionato" o // "Pagina caricata, ma stato non OK. "console.error (risultato););

Sapevo che potevamo fidarci di te, mia promessa.

Promesse di concatenamento

Ora, potreste pensare a questo punto che le promesse sono solo funzioni di callback fantasiose con una sintassi migliore. Questo è vero fino a un certo punto, ma per continuare con il nostro esempio AJAX, dì che hai bisogno di fare poche altre richieste, ogni richiesta basata sul risultato dell'ultimo. O se fosse necessario prima elaborare il JSON? 

Fare questo con i callback finirebbe con un pesante annidamento di funzioni, ognuna delle quali diventa sempre più difficile da seguire. Fortunatamente, nel mondo delle promesse possiamo concatenare tali funzioni insieme in questo modo. Ecco un esempio in cui una volta che riceviamo il JSON per il commento di un utente sul nostro blog fasullo, allora vogliamo assicurarci che sia tutto in minuscolo prima di fare qualcos'altro con esso.

myPromise .then (function (result) // Una volta ricevuto JSON, // lo trasformo in un oggetto JSON e restituisce. return JSON.parse (result);) .then (function (parsedJSON) // Una volta json ha stato analizzato, // recupera l'indirizzo email e lo rende in caratteri minuscoli. return parsedJSON.email.toLowerCase ();) .then (function (emailAddress) // Una volta che il testo è stato scritto in lettere minuscole, // stampalo sulla console. console.log (emailAddress);, function (err) // Qualcosa nella catena precedente è andato storto? // Stampa scarto in uscita. console.error (err););

Potete vedere qui che mentre la nostra chiamata iniziale era asincrona, è possibile associare anche le chiamate sincrone. Il codice in ciascuno risolvere funzione all'interno del poi sarà chiamato quando ognuno ritorna. Noterai anche che c'è una sola funzione di errore specificata qui per l'intera catena. Mettendo questo alla fine della catena come il rifiutare funzione nell'ultimo poi, qualsiasi promessa nella catena che chiama rifiutare chiamerà questo.

Ora che siamo un po 'più fiduciosi delle promesse, creiamo un altro in combinazione con quello sopra. Ne creeremo uno che prende il nostro nuovo indirizzo email in lettere minuscole e invierà (fingiamo) un messaggio di posta elettronica a quell'indirizzo. Questo è solo un esempio per illustrare qualcosa di asincrono, potrebbe essere qualsiasi cosa, come contattare un server per vedere se l'email era su una lista bianca o se l'utente è loggato. Dovremo dare l'indirizzo email alla nuova promessa, ma le promesse non accettano argomenti. Il modo per aggirare questo è avvolgere la promessa in una funzione che fa, in questo modo:

var sendEmail = function (emailAddress) return new Promise (funzione (risoluzione, rifiuto) // Fingere per inviare un'email // o fare qualcos'altro setTimeout asincrono (function () resolve ('Email inviata a' + emailAddress); , 3000);); ;

Stiamo usando il setTimeout chiama qui per fingere semplicemente un'attività che richiede alcuni secondi per essere eseguita in modo asincrono.

Quindi, come usiamo la nostra nuova funzione di creazione di promesse? Bene, dal momento che ciascuno risolvere funzione utilizzata all'interno di a poi dovrebbe restituire una funzione, quindi possiamo usarla in modo simile ai nostri task sincroni.

myPromise .then (function (result) return JSON.parse (result);) .then (function (parsedJSON) return parsedJSON.email.toLowerCase ();) .then (function (emailAddress) return sendEmail (emailAddress )) .then (function (result) // Output "Email inviata a [email protected]" console.log (risultato);, function (err) console.error (err););

Andiamo oltre questo flusso solo per riassumere cosa sta succedendo. La nostra promessa originale mia promessa richiede un pezzo di JSON. Quando viene ricevuto quel JSON (non sappiamo quando), trasformiamo il JSON in un oggetto JavaScript e restituiamo quel valore. 

Una volta fatto, prendiamo l'indirizzo email dal JSON e lo facciamo in minuscolo. Quindi inviamo una e-mail a quell'indirizzo, e ancora non sappiamo quando sarà completata, ma quando lo farà manderemo un messaggio di successo alla console. Nessun nidificazione pesante in vista.

Conclusione

Spero che questa sia stata un'introduzione utile a Promises e ti ha dato buoni motivi per iniziare a usarli nei tuoi progetti JavaScript. Se vuoi saperne di più su Promises in maggiore dettaglio, consulta l'eccellente articolo di HTML5 Rocks di Jake Archibald su questo argomento.

Scopri JavaScript: la guida completa

Abbiamo creato una guida completa per aiutarti a imparare JavaScript, sia che tu stia appena iniziando come sviluppatore web o che desideri esplorare argomenti più avanzati.