I en del av denna handledning lärde vi oss principerna bakom asynkron programmering och användningsanrop. För att granska, tillåter asynkron programmering oss att skriva kod som inte blockeras genom att exekvera blockeringsuppgifter senare. Återuppringningsfunktionerna ger ett sätt att synkronisera körning av vår kod.
Nästande återuppringningar är dock inte ett gott mönster att följa. Här kommer löften till undsättning. Löften har använts ett tag i JavaScript-bibliotek, men nu kan du använda dem inhemskt i din kod. Async-funktionerna förbättrar löften genom att låta oss skriva våra uppgifter efter varandra utan att behöva oroa sig för tidpunkten för deras genomförande.
Låt oss ta en titt på vad ett löfte är konceptuellt. Tänk på scenariot där du handlar online och du köper ett par skor. När du checkar ut skickas en sammanfattning av ditt köp.
Denna orderbekräftelse är som ett löfte. Löftet är din garanti för att du kommer att få tillbaka något senare från företaget. Medan din beställning är pågående slutar inte ditt liv naturligtvis. Du fortsätter att göra andra uppgifter som att surfa på internet. Om din beställning är uppfylld får du ett mail med fraktinformationen. Det är möjligt att din beställning avvisas. Varan du beställde kan vara slut i lager, eller det kan vara ett problem med din betalningsmetod. I det här fallet får du ett e-postmeddelande som berättar om felet.
I kodtal är ett löfte ett objekt som säkerställer att vi får ett framtida värde för vår begäran om det lyckas eller misslyckas. Detta är den allmänna formen för att skapa och använda ett löfte:
funktionsuppgift1 () returnera nytt löfte (funktion (lösa, avvisa) lösa (data); avvisa (fel);); task1 () .then (funktion (resultat) console.log (result);) .catch (funktion (fel) console.log (error););
För att skapa ett löfte skapar du ett löfteobjekt och skriver din asynkrona kod inuti löftet återuppringningsfunktion. De uppgifter du vill ha tillbaka från löftet skickas som ett argument till lösa
funktionen och ditt felmeddelande skickas in i avvisa
fungera. Vi kedjar tillsammans löften med hjälp av sedan
metod. Detta låter oss utföra uppgifterna i följd.
Om vi behöver överföra resultaten av en uppgift till nästa uppgift, returnerar vi den i sedan
metod. Vi kanske vill kedja löften tillsammans när vi är intresserade av att omvandla värden eller vi behöver utföra vår kod i en viss ordning. I slutet av kedjan tar vi våra fel. Om ett fel uppstår i någon av våra uppgifter, hoppas de återstående uppgifterna över, och felet skickas till vårt fångstblock.
I en del av denna handledning använde vi callbacks för att öppna en fil och hämta ett inlägg och dess kommentarer. Det här är vad den fullständiga koden ser ut som att använda löften:
const fs = kräver ('fs'); const path = kräver ('path'); const postsUrl = path.join (__ dirname, 'db / posts.json'); const commentsUrl = path.join (__ dirname, 'db / comments.json'); // returnera data från vår filfunktion loadCollection (url) returnera nytt Promise (funktion (lösa, avvisa) fs.readFile (url, "utf8", funktion (fel, data) if (error) reject fel "); annat lösa (JSON.parse (data)););); // returnera ett objekt med id-funktion getRecord (samling, id) returnera nytt Promise (funktion (lösa, avvisa) const data = collection.find (funktion (element) return element.id == id;); lösa (data);); // returnera en rad kommentarer för en postfunktion getCommentsByPost (kommentarer, postId) return comments.filter (funktion (kommentar) return comment.postId == postId;); // initieringskod loadCollection (postsUrl) .then (funktion (inlägg) return getRecord (inlägg, "001";) .then (funktion (post) console.log (post); return loadCollection (commentsUrl); ()
Skillnaden här är att vår metod att öppna filen är nu inslagna i ett löfteobjekt. Och i stället för att nesta våra uppgifter med callbacks, är de kedjda tillsammans med sedan
.
Som du kan se har vi inte eliminerat behovet av återuppringningar. Vi använder bara dem på olika sätt. Innan vi näste våra återuppringningar så att vi kunde fortsätta att utföra vår kod i nästa uppgift.
Detta påminner mig om när jag ringer kundservice om ett problem och i stället för agenten som löser mitt problem får jag överföring till någon annan. Att någon annan kan eller inte löser upp samtalet, men när det gäller den första agenten är det någon annans ansvar.
Med löften kommer vi att få tillbaka något innan vi går vidare till nästa uppgift. Om vi behöver överföra det till nästa fortsättning av vår kod kan vi använda en sedan
påstående.
Använd löften genom att skriva ett program som öppnar en fil med användare, få användarens information och öppna en fil med inlägg och skriva ut alla användarens inlägg.
Löften är en förbättring av utformningen av vårt program, men vi kan göra det bättre. Det skulle vara väldigt bekvämt om vi kunde utföra våra uppgifter synkront så här:
uppgift 1(); task2 (); task3 ();
Tja, vi kan med async / await mönstret. För att göra detta börjar vi genom att förpacka våra uppgifter i en async-funktion. Den här funktionen returnerar ett löfte. Då genomför vi felhantering genom att förpacka våra uppgifter inuti en försök fånga
påstående.
Om löftet är uppfyllt, kommer det att slutföra vilka uppgifter som var inuti vårt Prova
blockera. Om det avvisas, fånga
block kommer att utföras. Lägger till vänta
nyckelord innan någon uppgift pausar vårt program tills uppgiften är klar.
Detta är den allmänna formen för att använda async-funktioner:
async-funktion initTasks () försök const a = vänta uppgift1 (); const b = väntar på uppgift2 (); const c = väntar uppgift3 (); // gör något med a, b och c fångst (fel) // gör något med felobjektet initTasks ();
Med hjälp av det här mönstret kan vi skriva om hur vi kör vår kod i vårt fils exempel.
async funktion getPost () försök const posts = vänta loadCollection (postsUrl); const post = vänta getRecord (inlägg, "001"); const kommentarer = vänta loadCollection (commentsUrl); const postComments = vänta getCommentsByPost (kommentarer, post.id); console.log (post); console.log (postComments); fångst (fel) console.log (error); getPost ();
Jag tycker om att strukturera vår asynkod med a försök fånga
uttalande eftersom det tydligt skiljer felhanteringskoden från vanlig kod. Om någon av koden i vår Prova
block orsakar ett fel, det kommer att hanteras av fånga
blockera. Dessutom kan vi lägga till en till sist
block som kommer att exekvera kod oavsett om våra uppgifter lyckas eller misslyckas.
Ett exempel på att använda det här mönstret är att när vi har uppringningskod måste vi utföra. Denna kod behöver inte nödvändigtvis vara i a till sist
blockera. Det kan skrivas efter fånga
uttalande, och det kommer att utföras. Löften har inte denna syntax inbyggd. Vi skulle behöva kedja en annan sedan
uttalande efter vår fånga
uttalande för att uppnå samma effekt.
Använd async / vänta, skriv ett program som öppnar en fil med användare, få användarens information och öppna sedan en fil med inlägg och skriva ut användarens info och alla deras inlägg.
Återuppringningar är inte inneboende onda. Passande funktioner i andra funktioner är ett användbart mönster i JavaScript. Återuppringningar blir ett problem när vi använder dem för att kontrollera flödet av vår applikationslogik. Eftersom JavaScript är asynkront måste vi ta hand om hur vi skriver vår kod eftersom uppgifterna inte nödvändigtvis slutar i den ordning de skrevs. Det är inte dåligt för att vi inte vill ha någon uppgift att blockera fortsättningen av programmet.
Löften är ett bättre mönster för att skriva asynkron kod. De fixar inte bara rubbningen av kapslade återuppringningar, men de håller också kontroll över resultatet av en uppgift inom uppgiften. Genom att överföra kontroll till en annan uppgift, om den här uppgiften är vår egen kod eller ett tredjeparts API, gör vår kod mindre tillförlitlig. Slutligen tillåter async-funktioner oss att skriva vår kod synkront, vilket är mycket mer intuitivt och lättare att förstå.