Beloftes houden met JavaScript

JavaScript wordt, door zijn populariteit en recente verbeteringen, steeds meer de beste vriend van de webprogrammeur. En net als alle beste vrienden houdt JavaScript zich aan zijn beloften. 

Dat klinkt misschien een beetje raar, maar het is waar. De meeste huidige browsers ondersteunen het zogenaamde Promise-object. Een belofte lijkt heel erg op een functie in die zin dat het een stukje code vertegenwoordigt of een taak die je op een bepaald moment in de toekomst zou willen uitvoeren.

Hier is hoe een belofte eruit ziet.

var myPromise = new Promise (function (resolve, reject) // Uit te voeren taak.);

Je kunt hier zien dat als we een belofte maken we er een enkel argument aan toevoegen, wat een functie is die code bevat die we op enig moment in de toekomst zouden willen uitvoeren. Je hebt misschien ook de twee argumenten opgemerkt in de functie die aan de belofte is doorgegeven, oplossen en afwijzen. Dit zijn ook functies en zijn onze manier om de belofte te vertellen of het heeft gedaan wat het beloofde te doen. Dit is hoe je ze zou gebruiken:

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

Deze belofte zal uiteraard altijd verdwijnen als de als verklaring zal altijd waar zijn. Dit is alleen voor leerdoeleinden - we zullen later iets realistischer doen - maar stel je voor het vervangen van de waar met een codefragment waarvan je niet 100% zeker was dat het zou werken.

Nu we een belofte hebben gemaakt, hoe gebruiken we die dan? Welnu, we moeten het vertellen wat die oplossen en afwijzen functies zijn. We doen dit door de beloften te gebruiken dan methode.

myPromise.then (functie (resultaat) // Callback oplossen. console.log (result);, functie (resultaat) // Callback weigeren. console.error (result););

Omdat onze if-verklaring altijd voorbij gaat waar controleer, de bovenstaande code zal altijd loggen "Hallo Tuts + fans!" naar de console. Het zal het ook meteen doen. Dit komt omdat de code in de constructor van onze Promise synchroon is, wat betekent dat het niet wacht op een bewerking om uit te voeren. Het heeft alle informatie die het nodig heeft om door te gaan en doet dit zo snel mogelijk. 

Waar beloftes echt schijnen, is echter als het gaat om asynchrone taken - taken waarbij je niet weet wanneer precies de belofte zal worden vervuld. Een echt voorbeeld van een asynchrone taak is het ophalen van een bron, bijvoorbeeld een JSON-bestand, via AJAX. We weten niet hoe lang de server gaat duren om te reageren en het kan zelfs mislukken. Laten we AJAX toevoegen aan onze beloftecode.

var myPromise = new Promise (functie (resolve, reject) // Standaard AJAX-aanvraag instellen en laden. var request = new XMLHttpRequest (); // Vraag commentaar van een gebruiker aan bij ons valse blog. request.open ('GET', ' http://jsonplaceholder.typicode.com/posts/1 '); // Stel de functie in om te bellen wanneer de resource is geladen. request.onload = function () if (request.status === 200) resolve (request. antwoord); else weigeren ('geladen pagina, maar status niet OK');; // Functie instellen om te bellen bij het laden mislukt request.onerror = function () reject ('Aww, didn \' t werk helemaal. '); request.send (););

De code hier is slechts standaard JavaScript voor het uitvoeren van een AJAX-aanvraag. We vragen een resource, in dit geval een JSON-bestand op een opgegeven URL, en wachten tot deze reageert. We zullen nooit precies weten wanneer. En we willen de uitvoering van ons script natuurlijk niet stoppen om daar op te wachten, dus wat moeten we doen? 

Nou, gelukkig hebben we deze code binnen een belofte geplaatst. Door het hier neer te zetten, zeggen we in feite: "Hé stuk code, ik moet nu gaan, maar ik bel je later en vertel je wanneer je het moet uitvoeren. Beloof het en vertel het me wanneer je klaar bent?" En de code zal zeggen: "Ja, natuurlijk, ik beloof het." 

Een belangrijk ding om op te merken in het bovenstaande stuk code is de roeping van de oplossen en afwijzen functies. Vergeet niet dat dit onze manier is om onze belofte te zeggen dat onze code wel of niet met succes is uitgevoerd. Anders zullen we het nooit weten.

Met behulp van dezelfde code uit ons standaardvoorbeeld kunnen we zien hoe ons AJAX-verzoek binnen de belofte nu werkt.

// Vertel onze belofte om de code uit te voeren // en ons te vertellen wanneer het klaar is. myPromise.then (functie (resultaat) // Afdrukken ontvangen JSON naar de console console.log (result);, functie (resultaat) // Afdrukken "Aww werkte niet" of // "Pagina geladen, maar status niet OK. "console.error (result););

Ik wist dat we je konden vertrouwen, mijn belofte.

Het koppelen van beloften

Nu denk je misschien dat beloften gewoon fancy callback-functies zijn met een mooiere syntaxis. Dat is tot op zekere hoogte waar, maar om door te gaan met ons AJAX-voorbeeld, stel dat je nog een paar verzoeken moet doen, elk verzoek op basis van het resultaat van het laatste. Of wat als u de JSON eerst moet verwerken?? 

Dit doen met callbacks zou eindigen in zwaar nesten van functies, die steeds moeilijker bij te houden zijn. Gelukkig kunnen we dergelijke functies in de beloftenwereld op dezelfde manier aan elkaar koppelen. Hier is een voorbeeld, wanneer we eenmaal de JSON ontvangen voor de opmerking van een gebruiker op onze valse blog, dan willen we zeker weten dat het allemaal in kleine letters is voordat we iets anders ermee doen.

myPromise .then (functie (resultaat) // Zodra we JSON hebben ontvangen, veranderen in een JSON-object en terugkeren. return JSON.parse (result);) .then (function (parsedJSON) // Once json has zijn geparseerd, // haal het e-mailadres op en maak het in kleine letters retourneer parsedJSON.email.toLowerCase ();) .then (function (emailAddress) // Zodra de tekst met kleine letters is gemaakt, // moet u deze naar de console afdrukken. console.log (emailAddress);, functie (err) // Iets in de bovenstaande ketting is fout gegaan? // Uitvoer weigeren. console.error (err););

U kunt hier zien dat terwijl onze eerste oproep asynchroon was, het ook mogelijk is om synchrone oproepen te ketenen. De code in elk oplossen functie binnen de dan wordt gebeld wanneer een ieder terugkeert. U zult ook opmerken dat hier slechts één foutfunctie voor de hele keten is gespecificeerd. Door dit aan het einde van de ketting te plaatsen als de afwijzen functie in de laatste dan, elke belofte in de keten die roept afwijzen zal deze noemen.

Nu we een beetje meer vertrouwen hebben in beloftes, laten we er nog een maken in combinatie met de bovenstaande. We zullen er een maken die ons nieuwe e-mailadres voor kleine letters bevat en we zullen (doen alsof) een e-mail sturen naar dat adres. Dit is slechts een voorbeeld om iets asynchroon te illustreren - het kan van alles zijn, zoals contact opnemen met een server om te zien of de e-mail op een witte lijst stond of als de gebruiker is ingelogd. We moeten het e-mailadres aan de nieuwe belofte geven, maar beloftes accepteren geen argumenten. De manier om dit te omzeilen is om de belofte in te sluiten in een functie die dat doet, zoals:

var sendEmail = function (emailAddress) return new Promise (function (resolve, reject) // Doe alsof je een email stuurt // of doe iets anders asynchrone setTimeout (function () resolve ('Email sent to' + emailAddress); , 3000);); ;

We gebruiken de setTimeout bel hier om gewoon een taak uit te voeren die een paar seconden duurt om asynchroon te draaien.

Dus hoe gebruiken we onze nieuwe belofte-creërende functie? Nou ja, sinds elk oplossen functie gebruikt binnen een dan zou een functie moeten teruggeven, dan kunnen we het op dezelfde manier gebruiken als onze synchrone taken.

myPromise .then (functie (resultaat) return JSON.parse (resultaat);) .then (functie (parsedJSON) return parsedJSON.email.toLowerCase ();) .then (function (emailAddress) return sendEmail (emailAddress )) .then (functie (resultaat) // Uitgangen "E-mail verzonden naar [email protected]" console.log (result);, function (err) console.error (err););

Laten we deze stroom doornemen om samen te vatten wat er aan de hand is. Onze oorspronkelijke belofte mijn belofte vraagt ​​een stuk JSON aan. Wanneer die JSON wordt ontvangen (we weten niet wanneer), veranderen we de JSON in een JavaScript-object en retourneren die waarde. 

Zodra dat is gebeurd, nemen we het e-mailadres uit de JSON en maken we het in kleine letters. Vervolgens sturen we een e-mail naar dat adres en opnieuw weten we niet wanneer het moet worden voltooid, maar als dat het geval is, sturen we een succesbericht naar de console. Geen zwaar nestelen in zicht.

Conclusie

Ik hoop dat dit een nuttige introductie is geweest op Promises en heeft je goede reden gegeven om ze te gaan gebruiken in je JavaScript-projecten. Als je meer wilt weten over Promises in meer detail, bekijk dan Jake Archibald's uitstekende HTML5 Rocks-artikel over dit onderwerp.

Leer JavaScript: de complete gids

We hebben een complete handleiding samengesteld om u te helpen JavaScript te leren, of u net bent begonnen als een webontwikkelaar of dat u meer geavanceerde onderwerpen wilt verkennen.