Javascript “Promises” og “Promise Chains” forklaret på almindeligt engelsk

Jeg har været meget begejstret for Promises, lige siden de blev introduceret for et år siden. Selv om der er mange indlæg og meninger, der flyder rundt, vil Promises ikke gøre din kode mere performant… de vil gøre den lettere at læse og forstå (hvilket i min bog ofte tæller for meget mere!)

I første del af dette indlæg vil jeg forklare den grundlæggende struktur af promises. Hvis du har styr på det, er du velkommen til at scrolle til den sidste halvdel af indlægget.

Promises forklaret på almindeligt dansk

Her er den grundlæggende struktur af en Promise i Javascript:

Der er en ret typisk (og undvigende) kodestump. Jeg vil forsøge at bryde ned, hvad der foregår.

For at starte med skal du kun fokusere på linje 1-15:

  • Der er instantieringen. Denne linje skaber grundlæggende et løfte. Et løfte i JS har brug for noget at gøre, en opgave. Så den funktion, du ser blive overført her – function (resolve,reject) {…} er denne opgave
  • Dernæst ser du opgavens krop. Du kan gøre ting her. Et eller andet sted i denne kodeblok skal du beslutte, om tingene gik godt eller skidt. Hvis du f.eks. brugte denne plads til at hente et billede, har du enten modtaget det (gik godt) … eller også har du ikke modtaget det (ikke så godt).
  • Hvis det gik godt, kalder du en eller anden funktion, der markerer dette løfte som “resolved”. Hvis tingene ikke gik som planlagt, vil du “afvise” dette løfte. (vi vil tale mere detaljeret om dette om et øjeblik)

Nu skal vi fokusere på den resterende del af kodestumpen, linjerne 17-27:

  • Så langt, i linjerne 1-15, har du kun defineret dit Promise-objekt
  • I linjerne 17 & 22 knytter du grundlæggende en handlers til det
  • promise.XXXX (hvor XXX kan være “.then” eller “.catch” osv.) kører i princippet den funktion, der er defineret i løftet (linje 1-15). Baseret på, hvordan tingene gik (løst eller afvist), kalder de funktionerne i henholdsvis “.then” og “.catch”. Så hvis dit løfte blev løst (…tingene gik godt), vil funktionen i .then(…) blive udført, ellers udføres funktionen i .catch(…).

NOTE:

  • “.then(function)” returnerer en Promise. Du må også kun kalde “.then(…)” eller “.catch(…)” på Promise-objekter.

Nu da vi har gennemgået det grundlæggende, skal vi se på et mere interessant eksempel på, hvad vi kan gøre med Promises.

Kædning af Promises for at udføre flere anmodninger

Problem: For nylig stødte jeg på en situation, hvor i jeg havde brug for at hente en masse URL’er efter hinanden. Svaret for hver URL skulle imidlertid håndteres forskelligt baseret på URL’en.

For at sikre dette indlæg, lad os antage, at de urls, der hentes, er:

  • google.com
  • apple.com
  • amazon.com

Her er en forenklet version af det script, jeg brugte til at håndtere dette:

Lad os bryde dette ned:

  • Linjer 1-11: Opret en simpel wrapper omkring AJAX Get-metoden, der leveres af jQuery. Dette vil simpelthen videregive svaret til den angivne callback.
  • Linjer 18-51: Jeg opretter derefter tre funktioner (ja! Funktioner!), der returnerer en JS Promise
  • Hvert løfte gør dette internt – bruger Ajax-wrapperen til at hente sin url, og når dataene/svaret er modtaget, gør den noget med dataene og kalder til sidst “resolve()”
  • I linje 54: Jeg kæder disse løfter efter hinanden. Bemærk, at hver af disse funktioner returnerer et løfte (og er ikke et løfte i sig selv). Det er derfor, jeg bruger “first()”.then(…) i modsætning til “first.then(…)”

For at tydeliggøre yderligere, er her en måde at se på løftekæden på.

Løftekæden – farvekodet med firkantede parenteser

På denne måde kan du sekventielt hente hver URL, håndtere den som ønsket og affyre “resolved()”-funktionen for at udløse den næste Promise i kæden 🙂

Bemærk: Hvis du forsøger at køre ovenstående kodestykke i browseren, skal du aktivere CORS. Her er en Chrome-udvidelse, der kan hjælpe med at gøre dette med et enkelt klik.

Håber du nød dette indlæg.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.