Jag har varit mycket entusiastisk över Promises ända sedan de introducerades för ett år sedan. Även om det finns många inlägg och åsikter som flödar runt, kommer Promises inte att göra din kod mer performant… de kommer att göra den lättare att läsa och förstå (vilket i min bok, ofta räknas för mycket mer!)
För den första delen av det här inlägget kommer jag att förklara den grundläggande strukturen för promises. Om du har koll på det kan du gärna scrolla vidare till den senare delen av inlägget.
Promises explained in plain english
Här är den grundläggande strukturen för en Promise i Javascript:
En ganska typisk (och svårfångad) kodbit där. Jag ska försöka bryta ner vad som händer.
För att börja, fokusera bara på raderna 1-15:
- Där finns instantieringen. Den här raden skapar i princip ett löfte. Ett löfte i JS behöver något att göra, en uppgift. Så den funktion du ser skickas in här – function (resolve,reject) {…} är den uppgiften
- Nästan ser du uppgiftens kropp. Du kan göra saker här. Någonstans i det här kodblocket måste du bestämma om det gick bra eller dåligt. Om du till exempel använder det här utrymmet för att hämta en bild har du antingen fått den (gick bra)… eller så har du inte fått den (inte så bra).
- Om saker och ting gick bra anropar du någon funktion som markerar det här löftet som ”resolved” (löst). Om saker och ting inte gick som planerat kommer du att ”avvisa” detta löfte. (vi kommer att prata mer ingående om detta om en liten stund)
Nu ska vi fokusera på den återstående delen av kodutdraget, raderna 17-27:
- So långt, i raderna 1-15, har du bara definierat ditt Promise-objekt
- På raderna 17 & 22, fäster du i princip en handlers till det
- löfte.XXXX (där XXX kan vara ”.then” eller ”.catch” etc.) kör i princip den funktion som definieras i löftet (raderna 1-15). Beroende på hur det gick (löst eller avslaget) anropar de funktionerna i ”.then” respektive ”.catch”. Så om ditt löfte löstes (…saker och ting gick bra) kommer funktionen i .then(…) att exekveras, annars exekveras funktionen i .catch(…).
NOTE:
- ”.then(function)” returnerar ett löfte. Dessutom får du bara anropa ”.then(…)” eller ”.catch(…)” på Promise-objekt.
När vi nu har täckt grunderna ska vi titta på ett intressantare exempel på vad vi kan göra med Promises.
Kedja av Promises för att utföra flera förfrågningar
Problem: Jag har nyligen stött på en situation där jag behövde hämta ett antal webbadresser efter varandra. Svaret för varje URL måste dock hanteras på olika sätt beroende på URL:
För det här inlägget antar vi att de URL:er som hämtas är:
- google.com
- apple.com
- amazon.com
Här är en förenklad version av det skript jag använde för att hantera detta:
Låt oss dela upp det här:
- Linjerna 1-11: Skapa en enkel omslagsform kring AJAX Get-metoden som tillhandahålls av jQuery. Detta kommer helt enkelt att skicka svaret till den angivna callbacken.
- Linjerna 18-51: Jag skapar sedan tre funktioner (ja! Funktioner!) som returnerar ett JS-löfte
- Varje löfte gör internt detta – använder Ajax-omslaget för att hämta sin url, och när data/svaret har tagits emot, gör den något med datan och ringer till slut ”resolve()”
- I linje 54: Jag kedjar dessa löften efter varandra. Observera att var och en av dessa funktioner returnerar ett löfte (och inte är ett löfte i sig självt). Det är därför jag använder ”first()”.then(…) i motsats till ”first.then(…)”
För att förtydliga ytterligare, här är ett sätt att se på löfteskedjan.
På det här sättet kan du sekventiellt hämta varje URL, hantera den som önskat och avfyra ”resolved()”-funktionen för att utlösa nästa löfte i kedjan 🙂
Notera: Om du försöker köra kodutdraget ovan i webbläsaren måste du aktivera CORS. Här finns ett Chrome-tillägg som kan hjälpa dig att göra detta med ett enkelt klick.
Hoppas att du gillade det här inlägget.