Introduktion till generatorer & Koa.js Del 1

Koa.js är ett uttrycksfullt nästa generations webbramverk skrivet för Node.js av personerna bakom Express och Connect-ramarna. Koa.js använder generatorer, som är en blödande kantfunktion av JavaScript, och har ännu inte gjorts i stabila versioner av Node.js. Koa har som mål att använda generatorer för att rädda utvecklare från spagetti av callbacks, vilket gör det mindre felaktigt och därmed mer hanterbart.

Med bara 550 koder är Koa en extremt lätt ram. Även efter det packar Koa i en elegant serie av metoder som innehållsförhandlingar, omdirigeringar, proxy support etc., vilket ger dig enkelhet och snabb utveckling, tillsammans med den granulära kontrollen över ditt nodprogram.

Installera nod

Nu innan vi börjar måste du ha minst Node-versionen 0.11.x eller större.

Du kan installera den senaste versionen av Node med N-modulen:

sudo npm installera -g n sudo n stabil 

Du kan också använda andra samhällsmoduler som nvm eller bygga den från källan. Observera att N också är en communitymodul.

För att köra en JS-fil som använder generatorer måste du tillhandahålla --harmoni flagga när du kör det.

Till exempel att köra app.js, skriv in följande kommando:

nod --harmony app.js

Eller för att spara dig från att komma in i den här flaggan varje gång kan du skapa ett alias med följande kommando:

alias node = "node --harmony"

För att köra din ansökan med generatorer, skriv bara in:

nod app.js

Mycket bra! Tänk också på att hela koden i den här artikeln är tillgänglig på GitHub. Gärna gaffel och leka med den.

För att förstå Koa måste du först förstå generatorer som bildar rammens ryggrad.

Vad är generatorer?

Med ES-6 har generatorer äntligen landat i det magiska landet av JavaScript. Om du har tidigare erfarenhet av generatorer i Lua, Python, Scheme, Smalltalk etc., så skulle du vara glad att veta att en mycket liknande sak har implementerats i JavaScript. 

 Generatorer är förstklassiga samrutiner i JavaScript som helt enkelt introducerar ett paus och spelgränssnitt på språket. Innan generatorer användes hela skriptet vanligtvis exekvera i topp till botten, utan ett enkelt sätt att stoppa kodkörning och återuppta med samma stack senare. Nu får vi händerna smutsiga med några exempel.

Enligt det nuvarande utkastet till ES-6-specifikationen måste vi använda en annan version av funktionsdefinitionen för att skapa en generatorfunktion. Det ser ut så här:

var generator_func = funktion * () ;

Här generator_func är bara en tom generatorfunktion.

Så vad vi kan göra är att använda avkastning sökord i funktionen för att stoppa körningen och spara den aktuella stacken.

Här är ett enkelt exempel som visar summan av en oändlig AP:

var r = 3; funktion * infinite_ap (a) for (;;) a = a + r; ge a;  var sum = oändlig_ap (5); console.log (sum.next ()); // returnerar värde: 8, gjort: false console.log (sum.next ()); // returnerar värde: 11, gjort: false

I ovanstående kod skapar vi ursprungligen en iteratorinstans som heter infinite_ap som inkluderar en oändlig slinga och om den körs under normala förhållanden, kan frysa utförandet.

Därefter lagrar vi en iteratorinstans i summa variabel.

Nu när vi ringer sum.next (), det återvänder värde: 8, gjort: false vilket innebär att det upphörde att genomföras på avkastning uttalande som returnerar värde som "a" och Gjort som "falskt" .

Här Gjort returnerar false tills exekveringen är oavslutad. När utförandet är fullständigt (i det ovannämnda fallet händer det aldrig) funktionen returnerar värde: odefinierat, gjort: true .

Här är en liten ändring av den tidigare koden för att visa slutet på utförandet:

var r = 3; funktion * infinite_ap (a) for (var i = 0; i < 3 ; i++)  a = a + r ; yield a;   var sum = infinite_ap(5); console.log(sum.next()); // returns  value : 8, done : false  console.log(sum.next()); // returns  value : 11, done: false  console.log(sum.next()); // returns  value : 14, done: false  console.log(sum.next()); //return  value: undefined, done: true  

I mer komplicerade program skulle du kontrollera och använda de återvände värdena och Gjort status.

Notera: Använder sig av avkastning utan fungera* skulle leda till ett tidigt fel.

Tillgängliga generatorer metoder

Här är några vanliga metoder som kommer att vara till nytta när du hanterar vaniljgeneratorer.

Var och en av metoderna nedan är endast tillgänglig i en generatorfunktion och skulle göra ett annat fel.

Nästa()

Detta används för att återuppta utförandet tillsammans med ett argument. Om inget passeras, blir odefinierat passerat som första argumentet.

Exempel: sum.next (5);

kasta()

Detta används för att kasta ett fel eller ett undantag vid något steg. Det gör felhantering mycket enklare. Att kasta ett fel kan leda till att filen körs, om den inte hanteras någonstans. Det enklaste sättet att hantera ett fel är att använda ett försök och fånga uttalandet. Denna metod tar ett enda argument som kan vara någonting.

Exempel: sum.throw (nytt fel ("detta är ett fel")); 

delegera avkastning

Generator delegation används för att ge en generator från en befintlig generator och kan användas för att komponera generatorer eller till och med iterera över en generator.

Vid delegering till en annan generator slutar den nuvarande generatorn att producera ett värde själv och börjar ge värden för den delegerade generatorn tills den är uttömd. Vid uttömning av den delegerade generatorn återgår generatorn tillbaka till sitt eget värde.

Det är väldigt mycket som att använda a för-in slinga över en generator, men undantagen från den delegerade generatorn sprids och kastas via den yttre generatorns kasta metod och bör hanteras på samma sätt. Här är ett exempel:

var consoleLogThunk = funktion (msg) return function () console.log (msg);  vargenerator = funktion * () yield consoleLogThunk ("Yo"); utbyte consoleLogThunk ("Dawg"); yield consoleLogThunk ("!!!");  var delegator_function = funktion * () yield consoleLogThunk ("Jag gav avkastning före delegerat utbyte"); utbyte * generator (); yield consoleLogThunk ("Jag gav efter delegerat avkastning");  var k = delegator_funktion (); k.next () värde ().; k.next () värde ().; k.next () värde ().; console.log (k.next ()); // Om du ringer k.next () kommer det att kasta ett typfel eftersom värdet är odefinierat vilket inte är en funktion 

Nu när du har en kort förståelse av generatorer i Javascript kan du använda dem för att skriva mycket tydligare och mindre felaktiga applikationer där du kan blockera på I / O utan att faktiskt blockera processen. 

Låt oss nu gå vidare till installationen av Koa och en mycket enkel applikation baserad på Koa.js.

Koa.js:

Koa är ett föremål som innehåller en uppsättning medelverksgeneratorfunktioner, som alla är sammansatta och exekverade på ett stackliknande sätt vid varje förfrågan.

Installera Koa

Utför följande kommando i din projektkatalog.

npm installera koa - save

Koa kommer automatiskt att hämtas och sparas i en package.json fil, om den existerar.

Trots Koas väldigt lilla fotavtryck innehåller den metoder för uppgifter som cache-friskhet, innehållsförhandlingar, omdirigeringar, proxy-support etc., utan att medverka i middleware.

Här är ett exempel hello-world ansökan:

var koa = kräver ("koa"); var app = koa (); app.use (funktion * () this.body = "Hej världen !!!";); app.listen (3000);

Koas kontrollflöde

NuKoa implementerar också downstreaming följt av uppströms kontrollflöde. I början kan det vara svårt att gissa, men när du går igenom exemplet nedan kommer sakerna att bli tydligare.

Här är ett exempel på kontrollflöde i Koa:

var koa = kräver ('koa') (); koa.use (funktion * (nästa) // gör någonting innan du ger / övergår till nästa generatorfunktion i linje som kommer att bli 1: a händelse i nedströms console.log ("A"); ge nästa; // gör något när körningen returnerar uppströms, det här är sista händelsen i uppströms console.log ("B");); koa.use (funktion * (nästa) // gör någonting innan du ger / övergår till nästa generationsfunktion i linje, detta ska vara 2: a händelsen nedströms console.log ("C"); ge nästa; // göra något när exekveringen returneras uppströms och detta skulle vara andra händelsen uppströms console.log ("D");); koa.use (funktion * () // gör någonting innan du ger / går vidare till nästa generatorfunktion i rad. Här skulle det vara sista funktionen downstream console.log ("E"); this.body = "hey guys" .log ("F"); // Första händelsen av uppströms (från sista till första)); koa.listen (3000); 

Koden ovan är ganska enkel. Observera att inte allt console.log uttalanden krävs men de kommer att hjälpa dig att tydligt förstå nedströms och uppströms exekveringsflöde av Koa.js .

Förstå exemplen "Execution Flow

När vi kör denna applikation och öppna upp localhost: 3000 i webbläsaren kan vi observera att console.logs i terminalen är inte i storleksordningen A-B-C-D-E-F. Inte heller är de i storleksordningen A-C-E-B-D-F.

Ordern är faktiskt A-C-E-F-D-B som avbildar nedströms av utbyten och uppströms beteende av utförandet i en Koa app.

Du kanske märker att den skrivs ut två gånger. Detta beror på en dubbel förfrågan från webbläsaren för att hämta favicon.

Tips: The koa.use (funktion) lägger till middleware-funktionen i programmet.

Sammanfattningsvis

Så det är det för del ett av denna handledning på JavaScript generatorer och Koa.js. Du har lärt dig om de flesta förutsättningarna, som generatorer, hur man använder dem, hur man använder delegerande avkastning och hur kontrollflödet fungerar i Koa.js.

I nästa del av denna handledning kommer vi dyka djupare in i Koa och lära dig hur du bygger en CRUD-applikation. Om du har några frågor eller kommentarer, var god kontakta mig eller bara släpp en kommentar nedan.