Kontakt os

Fra webapplikationer til servere og mobilapps, fra små programmer til store projekter, JavaScript er overalt. Det er det vigtigste valg at omfavne ethvert projekt, fordi det er 2020, og JS er et endnu mere modent sprog med et enormt samfund, der understøtter det.

I JavaScript kører al kode synkront på hændelsesløkken, som udfører sekventielt små bidder af vores program. På hændelsessløjfen kaldes hver iteration en „kryds“ og kører, indtil køen er tom. Hvert stykke har en „kryds“ at behandle, og når det er afsluttet, starter den næste. For små applikationer er dette nok, men da vi begynder at udføre tungere operationer, der kræver mere tid, som at få adgang til en database eller hente data over Internettet, har vi brug for bedre mekanismer til at håndtere dem.
I årenes løb opstod mønstre og biblioteker i JS økosystem til at håndtere asynkron programmering, såsom tilbagekald, begivenheder, løfter, generatorer, async/wait, webarbejdere og pakker på NPM-registreringsdatabasen som async, bluebird, co eller RxJS.
Hvad angår front-end-udviklere, skal vi muligvis bruge forskellige mønstre til at løse de udfordrende problemer hver dag afhængigt af den ramme, vi arbejder på. At kende de tilgængelige værktøjer i JavaScript-verdenen giver os mulighed for at vælge den bedste løsning til hvert problem.
Du kan spørge, om denne vejledning kun er til webudvikling? Nej, de fleste af disse mønstre bruges i alle JavaScript-miljøer og -platforme, så at vide, hvordan de fungerer, er altid værdifuldt for enhver udvikler.
I JavaScript er funktioner førsteklasses objekter og a tilbagekald er bare en funktion, der sendes som et argument til en anden funktion. Også kendt som højordensfunktioner, skal tilbagekaldet påberåbes, når det asynkrone arbejde er afsluttet.
Da tilbagekald kun er funktioner, understøttes de af alle miljøer, der kører JavaScript, fra vores browsere til servere, der kører Node.js. Enkelt, men alligevel kraftfuldt, dette mønster er grundlæggende i asynkroni. Det har dog også sine ulemper.
Når projekter begynder at vokse, og vi skal begynde at lave mere kompleks kode, bliver det sværere at implementere generiske løsninger på vores programmer, hvilket gør dem sværere at læse og vedligeholde. Når dette sker, begynder vi at have pyramideformen på `}) `svarende til det, vi kan se i det følgende eksempel.
Dette er normalt kendt som „Tilbagekallingshelvede“.
Det værste, vi kan have med tilbagekald, er imidlertid inversionen af kontrol. Hvis dette sker, giver vi kontrol over programflowsekvensen til andre parter, hvilket gør det vanskeligt (eller endda umuligt!) for at teste det ordentligt.
En hændelsesdrevet arkitektur kan også bruges til at skrive asynkron javascript-kode. Denne arkitektur består af at have en hændelsesemitter med en tilsvarende hændelseslytter, der sender begivenheder, når async-koden er afsluttet. Afsendelse af forskellige typer begivenheder gør det muligt at have forskellige tilbagekald for hver type lyttere. Et grundlæggende eksempel og virkelig vigtig del af front-end-udviklingen er at anmode om data over internettet. For at opnå dette kunne vi bruge XMLHttpRequest objekt, der er stærkt brugt på AJAX programmering.
XMLHttpRequest-objektet har allerede nogle hændelseslyttere defineret til at håndtere anmodningsflowet, så vi skal bare drage fordel af dem. Men dette mønster har masser af kodelkode, da vi kunne tilføje og fjerne lyttere afhængigt af de forskellige begivenhedstyper, vi har brug for. Dette fungerer perfekt på en lille webside, men så snart kompleksiteten og funktionaliteterne vokser, begynder det at være oppustet og besværligt at vedligeholde, så bedre abstraktioner er nødvendige!
løfter er sværere at mestre, men adresserer inversionen af kontrolproblemet. De er lidt langsommere end tilbagekald, men til gengæld får vi en masse pålidelighed.
Vi kan altid være sikre på, at et løfte vil løse eller afvise, da de er en „indpakning“ omkring en værdi, der muligvis ikke eksisterer endnu. Løfter er en pålidelig mekanisme, der også hjælper med at udtrykke async-kode mere sekventielt. De kan højst have én opløsningsværdi, hvilket betyder, at et løfte altid skal løses eller afvises.
Sådan løser de inversionen af kontrol. Ikke ved at fjerne tilbagekald, men ved at oprette en mekanisme på indpakningen, der håndterer dette problem.
Vi kan kæde flere løfter på vores kode uden at tvinge et nyt niveau af indrykning efter hver enkelt ved hjælp af .then ().
Løfter giver mere funktionalitet, som for eksempel Promise.all () og Promise.race () vs de nyeste API-tilføjelser Promise.allSettled () og Promise.any (). Med mere komplekse front-end webapplikationer har vi brug for flere og bedre mekanismer.
Dette forbedrer kodens læsbarhed og vedligeholdelsesevnen af programmet også, men ikke alt er perfekt. Da denne funktion er på rammeniveau, kan flere implementeringer variere afhængigt af adfærd plus de faste omkostninger til tid og hukommelse.
Generatorer blev introduceret på ECMAScript 2015 og er funktioner, hvor vi kan bruge og styre iteratoren, hvilket betyder, at funktioner kan sættes på pause og genoptages til enhver tid. Dette er et kraftfuldt værktøj, når vi kun ønsker at få hver værdi, når vi har brug for det, i stedet for at få dem alle på én gang. Dette er muligt med tilføjelsen af ordet afkast til JavaScript.
Vi kan i dette eksempel se, at for hver næste () vi modtager et objekt med værdien og et flag, der angiver, om generatorfunktionerne sluttede. Men generatorer kan også bruges til at styre async-strømme i konjugationer med andre biblioteker, som i co eller redux-saga, som jeg vil tale mere om længere fremme.
Endelig blev ES2017 introduceret asynkrone funktioner gør det meget nemmere at skrive og læse asynkron kode i JavaScript!
De er meget renere end de sidste diskuterede mønstre, og tilbagevenden af en async-funktion er et løfte! Dette er meget magtfuldt, fordi vi har begge verdeners godhed. Som vi har diskuteret før, er løfter det sikre valg, når man beskæftiger sig med komplekse async-operationer, men de er ikke så lette at læse og mestre som async/waiting-kode.
En ulempe er, at den har brug for en transpilation værktøj, ligesom Babel, fordi Async/Await stadig er syntaktisk sukker over løftskoden.
Da resultatet er et løfte og kan løses/afvises, er det vigtigt at pakke vores ventekode ind i en try/catch. På denne måde kan vi korrekt håndtere fejl på vores async-kode.
Ved hjælp af webarbejdere er det muligt at køre scripts og funktioner på en anden tråd og køre kode i asynkrone baggrundsopgaver. Dette påvirker ikke brugergrænsefladens anvendelighed og kan sende data mellem arbejdere og hovedtråden.
Servicearbejderen i vores browsere bruges stærkt på progressive webapplikationer. Dette består i at registrere en webarbejder til vores websted og beslutte, hvilke filer der kan cachelagres eller ej, og det vil gøre appbrugen hurtigere. Også, hvis brugeren er offline, vil nogle funktioner stadig være tilgængelige. De kan også bruges til at udføre tunge operationer uden at fryse brugergrænsefladen eller JS-hovedtråden.
Flere andre biblioteker forsøger at løse disse problemer, hver ved hjælp af sine teknikker. Du kan finde nogle eksempler fremover:
Asynkron: dette bibliotek er godt til at arbejde med tilbagekald, der forsøger at løse nogle problemer, der findes inden for dem, samt eliminere callback-helvedesproblemet! I de sidste implementeringer er det også muligt at bruge Async/wait kode.
Blåfugl: en meget effektiv implementering af Promises, der også indeholder en masse ekstra funktioner som annullering, iteration og Promisify! Denne sidste er en indpakning omkring funktioner, der arbejder med tilbagekald, og returnerer et løfte for disse funktioner.
co: styre async-strømme med generatorer. Dette bibliotek er en runtime omkring generatorer, der kombinerer nøgleordsudbyttet med løfter, udfører generatorresultatet og returnerer det som et løfteobjekt.
Redux saga: Et front-end-bibliotek til React/Redux stack. Dette er en Redux middleware, der sigter mod at gøre applikationsbivirkninger mere effektive og lettere at administrere, da de kan startes eller annulleres af Redux handlinger. Denne implementering gør stor brug af generatorer til at hente data over internettet og anvende de nødvendige bivirkninger på vores hjemmeside.
RxJs: Dette er et mønster, der bruges på Angular apps, og det er et reaktivt mønster. Vi opretter en observerbar, som vi kan abonnere på og vente på ændringer, som vi får besked om. Ved hjælp af dette mønster er det muligt at annullere abonnementer og kædeobservabler, for eksempel.
For enkle projekter er tilbagekald den enkleste og nemmere måde at håndtere async-strømme på. På større projekter med en ordentlig opsætning ville jeg vælge async/waiting-mønsteret, da asynkroniciteten er let at læse, har en naturlig fejlhåndtering, og der ikke er nogen dødspyramide.
Dette er den slags syntaktisk sukker, vi har brug for på vores arbejde, så vi kan skrive et mere læsbart og vedligeholdeligt program.

Som det ses på ovenstående billede, er JavaScript fortsat det mest anvendte sprog på GitHub sammen med dets livlige samfund.
Dette er vores bedste valg til håndtering af asynkrone strømme, men der er flere måder at opnå de samme resultater ud over dem, som denne vejledning beskriver. Alt i alt er det op til dig at vælge, hvad der passer bedst til dine behov.


Full-stack udvikler og JavaScript-elsker. Top notch front-end er min ting, hvor jeg kan lide at eksperimentere med nye ting. Kajakfisker, brygger og øldrikker!
People who read this post, also found these interesting: