kontakta oss

Från webbapplikationer till servrar och mobilappar, från små program till stora projekt, JavaScript finns överallt. Det är huvudvalet att omfamna alla projekt eftersom det är 2020 och JS är ett ännu mer moget språk, med en enorm gemenskap som stöder det.

I JavaScript körs all kod synkront på händelselingan, som kör sekventiellt små bitar av vårt program. I händelselingan kallas varje iteration en ”kryssa” och körs tills kön är tom. Varje bit har en ”kryssa” att bearbeta och när det är klart börjar nästa. För små applikationer räcker det, men när vi börjar göra tyngre operationer som kräver mer tid, som att komma åt en databas eller hämta data över Internet, behöver vi bättre mekanismer för att hantera dem.
Under åren, mönster och bibliotek uppstod i JS ekosystem för att hantera asynkron programmering, såsom återuppringningar, händelser, löften, generatorer, async/wait, webbarbetare och paket på NPM-registret som async, bluebird, co eller RxJS.
När det gäller front-end-utvecklare kan vi behöva använda olika mönster för att lösa de utmanande problemen varje dag beroende på vilket ramverk vi arbetar med. Genom att känna till de tillgängliga verktygen i JavaScript-världen kan vi välja den bästa lösningen för varje problem.
Du kanske frågar om den här guiden endast är för webbutveckling? Nej, de flesta av dessa mönster används i alla JavaScript-miljöer och plattformar, så att veta hur de fungerar är alltid värdefullt för alla utvecklare.
I JavaScript är funktioner förstklassiga objekt och a ring tillbaka är bara en funktion som skickas som ett argument till en annan funktion. Även känd som högordningsfunktioner, bör återuppringningen åberopas när det asynkrona arbetet är klart.
Eftersom återuppringningar bara är funktioner stöds de av alla miljöer som kör JavaScript, från våra webbläsare till servrar som körs Node.js. Enkelt, men ändå kraftfullt, detta mönster är grundläggande i asynkroni. Men det har också sina nackdelar.
När projekt börjar växa och vi måste börja göra mer komplex kod blir det svårare att implementera generiska lösningar på våra program, vilket gör dem svårare att läsa och underhålla. När detta händer börjar vi ha pyramidformen på `}) `liknande det vi kan se i följande exempel.
Detta är vanligtvis känt som ”Återuppringningshelvetet”.
Men det värsta som vi kan ha med återuppringningar är inversionen av kontrollen. Om detta händer ger vi kontroll över programflödessekvensen till andra parter, vilket gör det svårt (eller till och med omöjligt!) för att testa det ordentligt.
En händelsedriven arkitektur kan också användas för att skriva asynkron javascript-kod. Denna arkitektur består av att ha en händelseemitter med en motsvarande händelseavlyssnare, som skickar händelser när asynkronkoden är klar. Att skicka olika typer av händelser gör det möjligt att ha olika återuppringningar för varje typ av lyssnare. Ett grundläggande exempel och riktigt viktig del av front-end-utvecklingen är att begära data över internet. För att uppnå detta skulle vi kunna använda XMLHttpRequest objekt som används starkt på AJAX programmering.
XMLHttpRequest-objektet har redan några händelseavlyssnare definierade för att hantera begäranflödet, så vi behöver bara dra nytta av dem. Men det här mönstret har massor av boilerplate-kod, eftersom vi kan lägga till och ta bort lyssnare beroende på de olika händelsetyper vi behöver. Detta fungerar perfekt på en liten webbsida men så snart komplexiteten och funktionaliteten växer börjar den bli uppblåst och besvärlig att underhålla, så bättre abstraktioner behövs!
Löften är svårare att bemästra, men tar itu med inversionen av kontrollfrågan. De är lite långsammare än återuppringningar, men i gengäld får vi mycket pålitlighet.
Vi kan alltid vara säkra på att ett löfte kommer att lösa eller avvisa eftersom de är ett ”omslag” kring ett värde som kanske inte existerar ännu. Löften är en pålitlig mekanism som också hjälper till att uttrycka asynkronkod mer sekventiellt. De kan ha, som mest, ett upplösningsvärde, vilket innebär att ett löfte alltid måste lösas eller avvisas.
Så här löser de inversionen av kontrollen. Inte genom att ta bort återuppringningar, utan genom att skapa en mekanism på omslaget som hanterar problemet.
Vi kan kedja flera löften på vår kod utan att tvinga en ny nivå av indragning efter varje, med hjälp av .then ().
Löften ger mer funktionalitet, som till exempel Promise.all () och Promise.race () jämfört med de senaste API-tilläggen Promise.allSettled () och Promise.any (). Med mer komplexa front-end webbapplikationer behöver vi fler och bättre mekanismer.
Detta förbättrar kodens läsbarhet och programmets underhållbarhet också, men inte allt är perfekt. Eftersom den här funktionen är på ramverksnivå kan flera implementeringar variera beroende på beteende, plus omkostnaderna för tid och minne.
Generatorer introducerades på ECMAScript 2015 och är funktioner där vi kan använda och styra iteratorn, vilket innebär att funktioner kan pausas och återupptas när som helst. Detta är ett kraftfullt verktyg för när vi bara vill få varje värde när vi behöver, istället för att få alla på en gång. Detta är möjligt med tillägget av ordet avkastning till JavaScript.
Vi kan se i detta exempel att för varje nästa () vi får ett objekt med värdet och en flagga som indikerar om generatorfunktionerna slutade. Men generatorer kan också användas för att styra asynkronflöden i konjugationer med andra bibliotek, som i co eller redux-saga, som jag kommer att prata mer om längre fram.
Slutligen infördes ES2017 asynkrona funktioner vilket gör det mycket lättare att skriva och läsa asynkron kod i JavaScript!
De är mycket renare än de senaste mönstren som diskuterades, och återkomsten av en async-funktion är ett löfte! Detta är mycket kraftfullt eftersom vi har godheten i båda världarna. Som vi har diskuterat tidigare är löften det säkra valet när man hanterar komplexa asynkroniska operationer, men de är inte så lätta att läsa och behärska som async/väntar kod.
En nackdel är att den behöver en transpilation verktyg, som Babel, eftersom Async/Await fortfarande är syntaktiskt socker över löfteskoden.
Eftersom resultatet är ett löfte och kan lösas/avvisas är det viktigt att packa in vår väntekod i ett try/catch. På så sätt kan vi hantera fel på vår async-kod korrekt.
Med hjälp av webbarbetare är det möjligt att köra skript och funktioner på en annan tråd, köra kod i asynkrona bakgrundsuppgifter. Detta påverkar inte användargränssnittets användbarhet och kan skicka data mellan arbetare och huvudtråden.
Servicearbetaren i våra webbläsare används starkt på progressiva webbapplikationer. Detta består av att registrera en webbarbetare för vår webbplats och bestämma vilka filer som kan cachelagras eller inte, och det kommer att göra appanvändningen snabbare. Även om användaren är offline kommer vissa funktioner fortfarande att vara tillgängliga. De kan också användas för att utföra tunga operationer utan att frysa användargränssnittet eller JS-huvudtråden.
Flera andra bibliotek försöker lösa dessa problem, var och en använder sina tekniker. Du kan hitta några exempel framöver:
Asynkron: det här biblioteket är bra att arbeta med återuppringningar som försöker lösa vissa problem som finns inom dem, samt eliminera återuppringningshelvetesproblemet! I de senaste implementeringarna är det möjligt att använda Async/wait kod också.
Blåhake: en mycket presterande implementering av Promises som också innehåller många extra funktioner som avbokning, iteration och Promisify! Den sista är ett omslag kring funktioner som arbetar med återuppringningar, vilket returnerar ett löfte för dessa funktioner.
co: styra asynkronflöden med generatorer. Detta bibliotek är en körning kring generatorer, kombinerar nyckelordsavkastningen med löften, kör generatorresultatet och returnerar det som ett löfteobjekt.
Redux saga: Ett front-end-bibliotek för React/Redux stack. Detta är en Redux middleware som syftar till att göra applikationens biverkningar effektivare och lättare att hantera, eftersom de kan startas eller avbrytas av Redux åtgärder. Denna implementering använder kraftigt generatorer för att hämta data över internet och tillämpa de nödvändiga biverkningarna på vår webbplats.
RxJs: Detta är ett mönster som används på Angular-appar och det är ett reaktivt mönster. Vi skapar en observerbar som vi kan prenumerera och vänta på ändringar som vi kommer att meddelas om. Med hjälp av detta mönster är det möjligt att avbryta prenumerationer och kedjeobserverbara objekt, till exempel.
För enkla projekt är återuppringningar det enklaste och enklare sättet att hantera asynkroniska flöden. På större projekt med en korrekt installation skulle jag välja async/wait-mönstret, eftersom asynkroniciteten är lätt att läsa, har en naturlig felhantering och det inte finns någon dödspyramid.
Detta är den typ av syntaktiskt socker vi behöver på vårt arbete, så att vi kan skriva ett mer läsbart och underhållbart program.

Som framgår av bilden ovan fortsätter JavaScript att vara det mest använda språket på GitHub, tillsammans med dess livliga community.
Detta är vårt bästa val för att hantera asynkrona flöden, men det finns fler sätt att uppnå samma resultat förutom de som den här guiden beskriver. Sammantaget är det upp till dig att välja vilken som är bäst för dina behov.


Full-stack utvecklare och JavaScript-älskare. Top notch front-end är min grej där jag gillar att experimentera med nya saker. Kajakfiskare, bryggare och öldrickare!
Människor som läste det här inlägget tyckte också att dessa var intressanta: