JavaScript-løfter forklaret

Hvad er et løfte i JavaScript?

JavaScript er enkelt gevind, hvilket betyder, at to bits script ikke kan køre på samme tid; de skal løbe den ene efter den anden. Et løfte er et objekt, der repræsenterer den endelige afslutning (eller fiasko) af en asynkron operation og dens resulterende værdi.

var promise = new Promise(function(resolve, reject) { // do thing, then… if (/* everything worked */) { resolve("See, it worked!"); } else { reject(Error("It broke")); } });

Der findes et løfte i en af ​​disse stater

  • Afventer: oprindelig tilstand, hverken opfyldt eller afvist.
  • Opfyldt: operationen blev gennemført med succes.
  • Afvist: operation mislykkedes.

Promise-objektet fungerer som proxy for en værdi, der ikke nødvendigvis er kendt, når løftet oprettes. Det giver dig mulighed for at knytte handlere til en asynkron handlings eventuelle succesværdi eller fejlårsag.

Dette lader asynkrone metoder returnere værdier som synkrone metoder: i stedet for straks at returnere den endelige værdi, returnerer den asynkrone metode et løfte om at levere værdien på et eller andet tidspunkt i fremtiden.

Brug af 'derefter' (løftekædning)

Hvis du vil tage flere asynkrone opkald og synkronisere dem efter hinanden, kan du bruge løftekæde. Dette gør det muligt at bruge en værdi fra det første løfte i senere efterfølgende tilbagekald.

Promise.resolve('some') .then(function(string) { // <-- This will happen after the above Promise resolves (returning the value 'some') return new Promise(function(resolve, reject) { setTimeout(function() { string += 'thing'; resolve(string); }, 1); }); }) .then(function(string) { // <-- This will happen after the above .then's new Promise resolves console.log(string); // <-- Logs 'something' to the console });

Promise API

Der er 4 statiske metoder i Promise-klassen:

  • Løfte. Løse
  • Løfte. Afvis
  • Lov. Alt
  • Lov. Løb

Løfter kan lænkes sammen

Når du skriver løfter om at løse et bestemt problem, kan du kæde dem sammen for at danne logik.

var add = function(x, y) { return new Promise((resolve,reject) => { var sum = x + y; if (sum) { resolve(sum); } else { reject(Error("Could not add the two values!")); } }); }; var subtract = function(x, y) { return new Promise((resolve, reject) => { var sum = x - y; if (sum) { resolve(sum); } else { reject(Error("Could not subtract the two values!")); } }); }; // Starting promise chain add(2,2) .then((added) => { // added = 4 return subtract(added, 3); }) .then((subtracted) => { // subtracted = 1 return add(subtracted, 5); }) .then((added) => { // added = 6 return added * 2; }) .then((result) => { // result = 12 console.log("My result is ", result); }) .catch((err) => { // If any part of the chain is rejected, print the error message. console.log(err); });

Dette er nyttigt til at følge et funktionelt programmeringsparadigme . Ved at oprette funktioner til manipulation af data kan du kæde dem sammen for at samle et endeligt resultat. Hvis en værdi på et tidspunkt i funktionskæden afvises , springer kæden til den nærmeste catch()handler.

For mere information om funktionel programmering: Funktionel programmering

Funktionsgeneratorer

I de seneste udgivelser har JavaScript introduceret flere måder til indbygget håndtering af løfter. En sådan måde er funktionsgeneratoren. Funktionsgeneratorer er "pauserbare" funktioner. Når de bruges sammen med Promises, kan generatorer gøre det meget lettere at læse og se ”synkron” ud.

const myFirstGenerator = function* () { const one = yield 1; const two = yield 2; const three = yield 3; return 'Finished!'; } const gen = myFirstGenerator();

Her er vores første generator, som du kan se ved function*syntaksen. Den genvariabel, vi erklærede, kører ikke myFirstGenerator, men i stedet “denne generator er klar til brug”.

console.log(gen.next()); // Returns { value: 1, done: false }

Når vi kører gen.next(), frigøres generatoren og fortsætter. Da dette er første gang, vi har kaldt gen.next(), kører den yield 1og holder pause, indtil vi ringer gen.next()igen. Når yield 1der kaldes, vil det returnere til os det, valueder blev givet, og om generatoren er det eller ej done.

console.log(gen.next()); // Returns { value: 2, done: false } console.log(gen.next()); // Returns { value: 3, done: false } console.log(gen.next()); // Returns { value: 'Finished!', done: true } console.log(gen.next()); // Will throw an error

Når vi bliver ved med at kalde, fortsætter gen.next()det med at gå videre til det næste yieldog holde pause hver gang. Når der ikke er flere yieldtilbage, fortsætter den med at køre resten af ​​generatoren, som i dette tilfælde simpelthen vender tilbage 'Finished!'. Hvis du ringer gen.next()igen, kaster det en fejl, når generatoren er færdig.

Forestil dig nu, at hvis hver yieldi dette eksempel var a Promise, ville selve koden virke ekstremt synkron.

Promise.all (iterable) er meget nyttigt for flere anmodninger til forskellige kilder

Metoden Promise.all (iterable) returnerer et enkelt Promise, der løses, når alle løfterne i det iterable argument er løst, eller når det iterable argument ikke indeholder løfter. Det afviser med grunden til det første løfte, der afviser.

var promise1 = Promise.resolve(catSource); var promise2 = Promise.resolve(dogSource); var promise3 = Promise.resolve(cowSource); Promise.all([promise1, promise2, promise3]).then(function(values) { console.log(values); }); // expected output: Array ["catData", "dogData", "cowData"]

Mere info om løfter:

  • Sådan fungerer JavaScript-løfter
  • Sådan implementeres løfter i JavaScript
  • Sådan bruges løfter i JavaScript
  • Sådan skriver du et JavsScript-løfte