Funcții de repetare a apelurilor JavaScript, promisiuni și asincrzi Partea 2

Introducere

În prima parte a acestui tutorial, am învățat principiile din spatele programării asincrone și folosind callback-urile. Pentru a examina, programarea asincronă ne permite să scriem cod care nu este blocat executând mai târziu sarcini de blocare. Funcția de returnare a apelurilor oferă o modalitate de a sincroniza execuția codului nostru. 

Cu toate acestea, inversarea apelurilor în mod repetat nu este un model bun de urmat. Aici vin promisiuni de salvare. Promisiunile au fost folosite pentru o perioadă în bibliotecile JavaScript, dar acum le puteți folosi în mod natural în codul dvs. Funcțiile Async se îmbunătățesc pe baza promisiunilor, permițându-ne să ne scriem sarcinile una după alta, fără să ne mai facem griji cu privire la calendarul execuției lor.

Cuprins

  • promisiuni
  • Async Funcții
  • Revizuire
  • Resurse

promisiuni

Să aruncăm o privire la ceea ce promisiunea este conceptuală. Imaginați-vă scenariul în care faceți cumpărături online și achiziționați o pereche de pantofi. Când ieșiți, primiți un rezumat al achiziției. 

Această confirmare a comenzii este ca o promisiune. Promisiunea este garanția că veți primi ceva mai târziu de la companie. În timp ce comanda dvs. este în așteptare, viața dvs. nu se oprește, bineînțeles. Continuați să faceți alte sarcini, cum ar fi navigarea pe internet. În cazul în care comanda dvs. este îndeplinită, veți primi un e-mail cu informațiile de expediere. Este posibil ca comanda dvs. să fie respinsă. Produsul pe care l-ați comandat poate fi în afara stocului sau ar putea apărea o problemă cu metoda dvs. de plată. În acest caz, veți primi un e-mail care vă va spune despre eroare.

În codul de vorbire, o promisiune este un obiect care asigură că vom obține o valoare viitoare pentru cererea noastră dacă reușește sau nu. Aceasta este forma generală pentru crearea și folosirea unei promisiuni:

funcția task1 () returnați noua promisiune (funcția (rezolvare, respingere) rezolva (date); respinge (eroare););  task1 () .then (functie (rezultat) console.log (rezultat);) .catch (functie (eroare) console.log (eroare););

Pentru a crea o promisiune, instanțiați un obiect promis și scrieți codul asincron în cadrul funcției de apel invers a promisiunii. Datele pe care doriți să le returnați din promisiune sunt transmise ca un argument către rezolva Funcția dvs. și mesajul de eroare este trecut în respinge funcţie. Noi lanțem împreună promisiunile folosind atunci metodă. Aceasta ne permite să executăm secvențial sarcinile. 

Dacă trebuie să transmitem rezultatele unei sarcini la următoarea sarcină, o vom returna în atunci metodă. Poate că ne dorim să promovam împreună promisiunile atunci când suntem interesați să transformăm valorile sau trebuie să executăm codul nostru într-o anumită ordine. La sfârșitul lanțului, ne prind erorile. Dacă apare o eroare în oricare dintre sarcinile noastre, sarcinile rămase sunt sărite și eroarea este trimisă blocului nostru de captură.

În prima parte a acestui tutorial, am folosit callbacks pentru a deschide un fișier și a prelua o postare și comentariile sale. Acesta este cel care arată codul complet folosind promisiunile:

index.js

const fs = necesită ("fs"); const path = necesită ('path'); const posturiUrl = path.join (__ dirname, 'db / posts.json'); const constUrl = path.join (__ dirname, 'db / comments.json'); // returnați datele din funcția noastră de fișier loadCollection (url) return new Promise (funcție (rezolvare, respingere) fs.readFile (url, 'utf8', funcție (eroare, date) if (error) eroare '); altceva resolve (JSON.parse (data));););  // returneaza un obiect prin functia id getRecord (colectie, id) returneaza noua Promise (functie (rezolva, respinge) const data = collection.find (function (element) return element.id == id; rezolva (date););  // returnează o serie de comentarii pentru o funcție post getCommentsByPost (comments, postId) returnează comments.filter (funcția (comment) return comment.postId == postId;);  // codul de initializare loadCollection (postsUrl) .then (functie (posturi) return getRecord (posturi, "001");) .then (function (post) console.log (post) return loadCollection (commentsUrl); ) .then (funcția (comentarii) const postComments = getCommentsByPost (comentarii, "001"); console.log (postComments);)) .catch (funcția (eroare) console.log (error);

Diferența este că metoda noastră de a deschide fișierul este acum înfășurată într-un obiect promis. Și în loc de a ne încadra sarcinile cu apeluri, acestea sunt înlănțuite împreună cu atunci

După cum puteți vedea, nu am eliminat nevoia de apelări. Noi le folosim doar în mod diferit. Înainte, ne-am imbricat callback-urile, astfel încât să putem continua execuția codului nostru în următoarea sarcină. 

Acest lucru îmi amintește de când sunam la serviciul clienți despre o problemă și în loc de agentul care rezolvă problema mea, mă transfer la altcineva. Că altcineva poate sau nu poate rezolva apelul, dar în ceea ce privește primul agent este responsabilitatea altcuiva. 

Cu promisiuni, vom obține ceva înapoi înainte de a merge la următoarea sarcină. Dacă avem nevoie să purtăm acel ceva la următoarea continuare a codului nostru, putem folosi a atunci afirmație.

Sarcină

Folosind promisiunile, scrieți un program care va deschide un fișier de utilizatori, obține informații despre utilizator, apoi deschideți un fișier de postări și tipăriți toate postările utilizatorului.

Async Funcții

Promisiunile reprezintă o îmbunătățire a designului programului nostru, dar putem face mai bine. Ar fi foarte convenabil dacă ne-am putea executa sarcinile în mod sincron ca acesta:

sarcina 1(); task2 (); task3 ();

Ei bine, putem cu asincia / asteptarea modelului. Pentru a face acest lucru, începem prin împachetarea sarcinilor noastre într-o funcție async. Această funcție returnează o promisiune. Apoi implementăm gestionarea erorilor prin împachetarea sarcinilor noastre în interiorul unui încearcă să prinzi afirmație. 

Dacă promisiunea este îndeplinită, ea va îndeplini toate sarcinile care au fost în interiorul nostru încerca bloc. Dacă este respinsă, captură bloc va fi executat. Adăugarea aștepta cuvântul cheie înainte de orice sarcină întrerupe programul nostru până la finalizarea sarcinii. 

Aceasta este forma generală pentru utilizarea funcțiilor de asincronizare:

funcția async initTasks () try const a = await task1 (); const b = așteaptă task2 (); const c = așteaptă task3 (); // face ceva cu a, b, și c captură (eroare) // face ceva cu obiectul de eroare initTasks ();

Folosind acest model, putem rescrie modul în care executăm codul nostru în exemplul nostru de fișiere.

funcția async getPost () încercați const posts = await loadCollection (postsUrl); const post = aștepta getRecord (posturi, "001"); const comments = așteaptă loadCollection (commentsUrl); const postComments = asteapta getCommentsByPost (comentarii, post.id); console.log (post); console.log (postComments);  captură (eroare) console.log (eroare);  getPost ();

Îmi place structurarea codului asincron cu a încearcă să prinzi deoarece separă în mod clar codul de manipulare a erorilor de codul obișnuit. Dacă vreunul din codul nostru încerca bloc cauzează o eroare, va fi tratată de către captură bloc. În plus, putem adăuga a in cele din urma bloc care va executa cod, indiferent dacă sarcinile noastre reușesc sau nu. 

Un exemplu de utilizare a acestui model este când avem codul de curățare pe care trebuie să-l executăm. Acest cod nu trebuie neapărat să fie inclus în a in cele din urma bloc. Poate fi scris după captură declarație, și va executa. Promisiunile nu au construit această sintaxă atunci declarație după noi captură pentru a obține același efect.

Sarcină

Folosind async / await, scrieți un program care va deschide un fișier de utilizatori, obține informații despre utilizator, apoi deschideți un fișier de postări și tipăriți informațiile utilizatorului și toate postările lor.

Revizuire

Revocările nu sunt în mod inerent răul. Transmiterea funcțiilor în alte funcții este un model util în JavaScript. Comenzile de returnare devin o problemă atunci când le folosim pentru a controla fluxul logicii aplicației noastre. Deoarece JavaScript este asincron, trebuie să avem grijă cum scriem codul nostru, deoarece sarcinile nu vor termina neapărat în ordinea în care au fost scrise. Nu este un lucru rău pentru că nu vrem să blocăm continuarea programului. 

Promisiunile sunt un model mai bun pentru scrierea codului asincron. Ele nu rezolvă doar aglomerația inversărilor inversate, dar ele păstrează și controlul rezultatului unei sarcini în cadrul acestei sarcini. Trecerea controlului la o altă sarcină, indiferent dacă acea sarcină este codul propriu sau un API terț, face ca codul nostru să fie mai puțin fiabil. În cele din urmă, funcțiile de asincracție ne permit să scriem codul nostru în mod sincron, ceea ce este mult mai intuitiv și mai ușor de înțeles.

Resurse

  • Nu știți JS: Async & Performance Ch 3: Promises
  • Promisiuni JavaScript: o introducere
  • Funcțiile Async: făcând promisiunile prietenoase
  • Async / Așteptați de Patrick Triest
Cod