Willkommen zum zweiten Teil unserer Serie über Generatoren und Koa. Wenn Sie es verpasst haben, können Sie hier den ersten Teil lesen. Stellen Sie vor dem Beginn des Entwicklungsprozesses sicher, dass Sie Node.js 0.11.9 oder höher installiert haben.
In diesem Teil werden wir eine Wörterbuch-API mit Koa.js erstellen. In Koa.js erfahren Sie mehr über Routing, Komprimierung, Protokollierung, Ratenbegrenzung und Fehlerbehandlung. Wir werden Mongo auch als Datastore verwenden und kurz lernen, wie man Daten in Mongo importiert und wie einfach das Abfragen in Koa ist. Zum Schluss betrachten wir das Debuggen von Koa-Apps.
Koa hat radikale Veränderungen unter der Haube, die die Generatorengüte von ES6 nutzen. Neben der Änderung des Kontrollflusses führt Koa auch eigene benutzerdefinierte Objekte ein, z diese
, diese Anfrage
, und diese Antwort
, Sie fungieren auf bequeme Weise als syntaktische Zuckerschicht, die auf den req- und res-Objekten von Node aufgebaut ist und Ihnen Zugriff auf verschiedene Komfortmethoden und Getter / Setter bietet.
Neben der Bequemlichkeit bereinigt Koa auch die Middleware, die sich in Express auf hässliche Hacks stützte, die häufig Kernobjekte modifizierten. Es bietet auch ein besseres Stream-Handling.
Eine Middleware ist eine steckbare Funktion, die bestimmte Funktionen hinzufügt oder entfernt, indem sie in den Request / Response-Objekten in Node.js etwas Arbeit erledigt.
Eine Koa-Middleware ist im Wesentlichen eine Generatorfunktion, die eine Generatorfunktion zurückgibt und eine andere akzeptiert. Normalerweise verfügt eine Anwendung über eine Reihe von Middleware, die für jede Anforderung ausgeführt werden.
Eine Middleware muss auch der nächsten "Downstream-Middleware" nachgeben, wenn sie von einer "Upstream-Middleware" ausgeführt wird. Wir werden mehr darüber im Abschnitt Fehlerbehandlung besprechen.
Nur noch eine letzte Sache: Um Ihrer Koa-Anwendung eine Middleware hinzuzufügen, verwenden wir die koa.use ()
Methode und geben Sie die Middleware-Funktion als Argument an. Beispiel: Anwendung (Koa-Logger)
fügt hinzu Koa-Logger
zur Liste der Middleware, die unsere Anwendung verwendet.
Um mit der Wörterbuch-API zu beginnen, benötigen wir eine Reihe von Definitionen. Um dieses reale Szenario neu zu erstellen, haben wir uns für einen echten Datensatz entschieden. Wir haben den Definitionsdump von Wikipedia genommen und ihn in Mongo geladen. Der Satz bestand aus etwa 700.000 Wörtern, da wir nur den englischen Dump importierten. Jeder Datensatz (oder jedes Dokument) besteht aus einem Wort, seinem Typ und seiner Bedeutung. Weitere Informationen zum Importieren finden Sie im import.txt
Datei im Repository.
Um den Entwicklungsprozess zu durchlaufen, klonen Sie das Repository und überprüfen Sie Ihren Fortschritt, indem Sie zu anderen Commits wechseln. Um das Repo zu klonen, verwenden Sie den folgenden Befehl:
$ git clone https://github.com/bhanuc/dictapi.git
Wir können mit dem Erstellen eines Basisservers beginnen:
var koa = erfordern ('koa'); var app = koa (); app.use (function * (next) this.type = 'json'; this.status = 200; this.body = 'Welcome': 'Dies ist eine Hello World-Anwendung der Stufe 2 !!';); if (! module.parent) app.listen (3000); console.log ('Hello World läuft unter http: // localhost: 3000 /');
In der ersten Zeile importieren wir Koa und speichern eine Instanz in der App-Variablen. Dann fügen wir in Zeile 5 eine einzige Middleware hinzu, eine anonyme Generatorfunktion, die die nächste Variable als Parameter übernimmt. Hier legen wir den Typ und Statuscode der Antwort fest, die ebenfalls automatisch ermittelt wird, können aber auch manuell eingestellt werden. Dann legen wir endlich den Körper der Antwort fest.
Da wir den Body in unserer ersten Middleware festgelegt haben, markiert dies das Ende jedes Anforderungszyklus und es wird keine andere Middleware involviert sein. Zum Schluss starten wir den Server durch Aufruf seines Hör mal zu
Methode und übergeben Sie die Portnummer als Parameter.
Wir können den Server starten, indem Sie das Skript folgendermaßen ausführen:
$ npm install koa $ node --harmony index.js
Sie können diese Stufe direkt erreichen, indem Sie zum Festschreiben wechseln 6858ae0
:
$ git checkout 6858ae0
Das Routing ermöglicht es uns, verschiedene Anforderungen auf der Grundlage des Anfragetyps und der URL an verschiedene Funktionen umzuleiten. Zum Beispiel möchten wir vielleicht antworten /Anmeldung
anders als Anmelden
. Dies kann durch Hinzufügen einer Middleware erfolgen, die die URL der erhaltenen Anforderung manuell überprüft und entsprechende Funktionen ausführt. Anstatt diese Middleware manuell zu schreiben, können wir auch eine von der Community erstellte Middleware verwenden, die auch als Middleware-Modul bezeichnet wird.
Um unserer Anwendung Routing-Funktionen hinzuzufügen, verwenden wir ein Community-Modul mit dem Namen Koa-Router
.
Benutzen Koa-Router
, Wir werden den vorhandenen Code in den unten gezeigten Code ändern:
var koa = erfordern ('koa'); var app = koa (); var router = erfordern ('koa-router'); var mount = required ('koa-mount'); var handler = function * (next) this.type = 'json'; this.status = 200; this.body = 'Welcome': 'Dies ist eine Hello-World-Anwendung der Stufe 2 !!'; ; var APIv1 = neuer Router (); APIv1.get ('/ all', Handler); app.use (mount ('/ v1', APIv1.middleware ())); if (! module.parent) app.listen (3000); console.log ('Hello World läuft unter http: // localhost: 3000 /');
Hier haben wir zwei Module importiert, wo Router
Shops Koa-Router
und montieren
speichert die Koa-Mount
Modul, so dass wir den Router in unserer Koa-Anwendung verwenden können.
In Zeile 6 haben wir unsere definiert Handler
Funktion, die dieselbe Funktion wie zuvor, aber hier haben wir ihr einen Namen gegeben. In Zeile 12 speichern wir eine Instanz des Routers in APIv1
, und in Zeile 13 registrieren wir unseren Handler für alle ERHALTEN
Anfragen auf der Route /alles
.
Also alle Anfragen, außer wenn eine Get-Anfrage gesendet wird localhost: 3000 / alle
wird "nicht gefunden" zurückgeben. Schließlich verwenden wir in Zeile 15 montieren
Middleware, die eine nutzbare Generatorfunktion gibt, die eingespeist werden kann app.use ()
.
Um diesen Schritt direkt zu erreichen oder Ihre Anwendung zu vergleichen, führen Sie den folgenden Befehl im geklonten Repo aus:
$ git checkout 8f0d4e8
Bevor wir unsere Anwendung ausführen, müssen wir jetzt installieren Koa-Router
und Koa-Mount
mit npm
. Wir stellen fest, dass mit zunehmender Komplexität unserer Anwendung auch die Anzahl der Module / Abhängigkeiten zunimmt.
Um alle Informationen über das Projekt zu verfolgen und diese Daten verfügbar zu machen npm
, Wir speichern alle Informationen in package.json
einschließlich aller Abhängigkeiten. Sie können package.json manuell oder mithilfe einer interaktiven Befehlszeilenschnittstelle erstellen, die mit der $ npm init
Befehl.
"name": "koa-api-dictionary", "version": "0.0.1", "description": "koa-api-dictionary-Anwendung", "main": "index", "author": " name ":" Bhanu Pratap Chaudhary "," email ":" [email protected] "," repository ": " type ":" git "," url ":" https://github.com/bhanuc/ dictapi.git "," license ":" MIT "," engine ": " node ":"> = 0.11.13 "
Ein sehr minimales package.json
Datei sieht aus wie oben.
Einmal package.json
vorhanden ist, können Sie die Abhängigkeit mit folgendem Befehl speichern:
$ npm installieren--sparen
Beispiel: In diesem Fall installieren wir die Module mit dem folgenden Befehl, um die Abhängigkeiten in zu speichern package.json
.
$ npm installiere den Koa-Router Koa-Mount --save
Jetzt können Sie die Anwendung mit ausführen $ node --harmony index.js
.
Sie können mehr darüber lesen package.json
Hier.
Wir beginnen mit dem Erstellen von zwei Routen für die API, eine für das Erzielen eines einzelnen Ergebnisses in einer schnelleren Abfrage und eine zweite, um alle übereinstimmenden Wörter zu erhalten (die zum ersten Mal langsamer sind)..
Um die Dinge übersichtlich zu halten, werden wir alle API-Funktionen in einem separaten Ordner mit Namen aufbewahren api
und eine Datei namens api.js
, und importieren Sie es später in unserem Hauptfenster index.js
Datei.
var Mönch = Anfordern ("Mönch"); var wrap = erfordern ('Co-Mönch'); var db = Mönch ('localhost / mydb'); var words = wrap (db.get ('words')); / ** * Holen Sie sich alle Ergebnisse. * / exports.all = function * () if (this.request.query.word) var res = Ergebnis words.find (word: this.request.query.word); this.body = res; else this.response.status = 404; ; / ** * Ein einzelnes Ergebnis erhalten. * / exports.single = function * () if (this.request.query.word) var res = Ertrag words.findOne (word: this.request.query.word); this.body = res; else this.response.status = 404; ;
Hier benutzen wir Co-Mönch
, das wirkt ein Wrapper herum Mönch
, Das macht es uns sehr leicht, MongoDB mit Generatoren in Koa abzufragen. Hier importieren wir Mönch
und Co-Mönch
, und verbinden Sie sich mit der MongoDB-Instanz in Zeile 3. Wir rufen an wickeln()
auf Sammlungen, um sie generatorenfreundlich zu machen.
Dann fügen wir zwei Generatormethoden hinzu alles
und Single
als Eigentum der Exporte
variabel, damit sie in andere Dateien importiert werden können. In jeder Funktion prüfen wir zuerst den Abfrageparameter 'word'. Wenn vorhanden, fragen wir nach dem Ergebnis oder wir antworten mit einem 404-Fehler.
Wir nehmen das Ausbeute
Schlüsselwort zum Warten auf die Ergebnisse, wie im ersten Artikel beschrieben, wodurch die Ausführung angehalten wird, bis das Ergebnis empfangen wird. In Zeile 12 verwenden wir die finden
Diese Methode gibt alle passenden Wörter zurück, die in res gespeichert und anschließend zurückgesendet werden. In Zeile 23 verwenden wir die einen finden
In der Sammlung verfügbare Methode, die das erste übereinstimmende Ergebnis zurückgibt.
var koa = erfordern ('koa'); var app = koa (); var router = erfordern ('koa-router'); var mount = required ('koa-mount'); var api = erfordern ('./ api / api.js'); var APIv1 = neuer Router (); APIv1.get ('/ all', api.all); APIv1.get ('/ single', api.single); app.use (mount ('/ v1', APIv1.middleware ())); if (! module.parent) app.listen (3000); console.log ('Dictapi läuft unter http: // localhost: 3000 /');
Hier importieren wir exportierte Methoden aus api.js
und wir weisen Handlern zu ERHALTEN
Routen /alles
/Single
und wir haben eine voll funktionsfähige API und Anwendung bereit.
Um die Anwendung auszuführen, müssen Sie nur das Programm installieren Mönch
und Co-Mönch
Module mit dem folgenden Befehl. Stellen Sie außerdem sicher, dass Sie über eine laufende Instanz von MongoDB verfügen, in der Sie die im git-Repository vorhandene Sammlung mithilfe der Anweisungen in importiert haben import.txtweird
.
$ npm install Mönch Co-Mönch --save
Jetzt können Sie die Anwendung mit dem folgenden Befehl ausführen:
$ node --harmony index.js
Sie können den Browser und die folgenden URLs öffnen, um die Funktion der Anwendung zu überprüfen. Ersetzen Sie einfach "neu" durch das Wort, das Sie abfragen möchten.
http: // localhost: 3000 / v1 / all? word = new
http: // localhost: 3000 / v1 / single? word = new
Um diesen Schritt direkt zu erreichen oder Ihre Anwendung zu vergleichen, führen Sie den folgenden Befehl im geklonten Repo aus:
$ git checkout f1076eb
Durch die Verwendung von kaskadierenden Middlewares können wir Fehler mit der versuchen / fangen
Mechanismus, da jede Middleware sowohl auf Downstream als auch auf Upstream reagieren kann. Also, wenn wir ein hinzufügen Versuchen und fangen Middleware zu Beginn der Anwendung, fängt es alle Fehler auf, die bei der Anforderung der restlichen Middleware aufgetreten sind, da es die letzte Middleware während des Upstreaming ist. Hinzufügen des folgenden Codes in Zeile 10 oder vorher in index.js
sollte arbeiten.
app.use (Funktion * (next) try yield next; // die Ausführung an Downstream-Middlewares übergeben) catch (err) // wird nur ausgeführt, wenn ein Fehler auftritt & keine andere Middleware auf die Anforderung this.type = antwortet 'json'; // optional hier this.status = err.status || 500; this.body = 'error': 'Die Anwendung hat sich gerade durchgesetzt, hoffentlich hat NSA alle Protokolle;)'; // delegiere den Fehler zurück an die Anwendung this.app.emit ('error', err, this); );
Das Speichern von Protokollen ist ein wesentlicher Bestandteil einer modernen Anwendung, da Protokolle beim Debuggen und beim Ermitteln von Problemen in einer Anwendung sehr hilfreich sind. Sie speichern auch alle Aktivitäten und können so verwendet werden, um die Aktivitätsmuster der Benutzer und andere interessante Muster herauszufinden.
Die Ratenbegrenzung ist auch zu einem wesentlichen Bestandteil moderner Anwendungen geworden, bei denen es wichtig ist, zu verhindern, dass Spammer und Bots Ihre wertvollen Serverressourcen verschwenden und dass sie Ihre API nicht auslaugen.
Es ist ziemlich einfach, unserer Koa-Anwendung Protokollierung und Ratenbegrenzung hinzuzufügen. Wir werden zwei Community-Module verwenden: Koa-Logger
und koa-besserer ratenbegrenzung
. Wir müssen der Anwendung den folgenden Code hinzufügen:
var logger = required ('koa-logger'); var limit = erfordern ('koa-better-ratelimit'); // Fügen Sie die Zeilen unterhalb der Fehler-Middleware hinzu. app.use (limit (duration: 1000 * 60 * 3, // 3 min max: 10, schwarze Liste: [])); app.use (logger ());
Hier haben wir zwei Module importiert und als Middleware hinzugefügt. Der Logger protokolliert jede Anfrage und druckt im stdout
des Prozesses, der leicht in einer Datei gespeichert werden kann. Durch die Beschränkung der Middleware wird die Anzahl der Anforderungen begrenzt, die ein Benutzer in einem bestimmten Zeitraum anfordern kann (hier sind es maximal zehn Anfragen in drei Minuten). Sie können auch ein Array von IP-Adressen hinzufügen, die auf die schwarze Liste gesetzt werden und deren Anfrage nicht verarbeitet wird.
Denken Sie daran, die Module zu installieren, bevor Sie den Code verwenden:
$ npm install koa-logger koa-better-ratelimit --save
Eine der Möglichkeiten, um eine schnellere Zustellung zu gewährleisten, ist das GZIP Ihrer Antwort, was in Koa relativ einfach ist. Um Ihren Verkehr in Koa zu komprimieren, können Sie die Koa-Kompresse
Modul.
Optionen können hier ein leeres Objekt sein oder je nach Anforderung konfiguriert werden.
var compress = erfordern ('koa-compress'); var opts = filter: function (content_type) return /text/i.test(content_type), // Filtern von Anforderungen, die mit Regex-Schwellenwert komprimiert werden sollen: 2048, // Mindestgröße für die Komprimierung von Flush: Requirement ('zlib') .Z_SYNC_FLUSH; // Verwenden Sie den folgenden Code, um die Middleware zur Anwendung app.use (compress (opts)) hinzuzufügen.
Sie können die Komprimierung in einer Anforderung sogar deaktivieren, indem Sie einer Middleware den folgenden Code hinzufügen:
this.compress = true;
Vergessen Sie nicht, compress mit zu installieren npm
.
$ npm install compress --save
Um diesen Schritt direkt zu erreichen oder Ihre Anwendung zu vergleichen, führen Sie den folgenden Befehl im geklonten Repo aus:
git checkout 8f5b5a6
Der Test sollte ein wesentlicher Bestandteil des gesamten Codes sein, und es sollte eine maximale Testabdeckung angestrebt werden. In diesem Artikel schreiben wir Tests für die Routen, die über unsere Anwendung zugänglich sind. Wir werden Supertest und Mocha verwenden, um unsere Tests zu erstellen.
Wir werden unseren Test in speichern test.js
in dem api
Mappe. In beiden Tests beschreiben wir zuerst unseren Test und geben ihm einen besser lesbaren Namen. Danach übergeben wir eine anonyme Funktion, die das korrekte Verhalten des Tests beschreibt und einen Rückruf durchführt, der den eigentlichen Test enthält. Bei jedem Test importieren wir unsere Anwendung, initiieren den Server, beschreiben Anfragetyp, URL und Abfrage und setzen die Kodierung auf gzip. Zum Schluss prüfen wir, ob die Antwort richtig ist.
var request = required ('supertest'); var api = required ('… /index.js'); beschreiben ('GET all', Funktion () it ('sollte mit allen Wörtern antworten'), Funktion (erledigt) var app = api; request (app.listen ()) .get ('/ v1 / all') .query (word: 'new') .set ('Accept-Encoding', 'gzip') .expect ('Content-Type', / json /) .expect (200) .end (done);) ) beschreiben ('GET / v1 / single', function () it ('sollte mit einem einzigen Ergebnis antworten'), function (done) var app = api; request (app.listen ()) .get ('/ v1 / single ') .query (word:' new ') .set (' Accept-Encoding ',' gzip ') .expect (200) .expect (' Content-Type ', / json /) .end ( function (err, res) if (err) werfen err; else if (! ('_ id' in res.body)) liefert "missing id"; if (! ('word' in res.body)) wirft neu Fehler ("fehlendes Wort"); done (););))
Um unseren Test durchzuführen, machen wir eine Makefile
:
test: @ NODE_ENV = test ./node_modules/.bin/mocha \ --require sollte \ --reporter nyan \ --harmony \ --bail \ api / test.js .PHONY: test
Hier haben wir den Reporter (Nyan Cat) und das Testframework (Mocha) konfiguriert. Beachten Sie, dass der Import hinzufügen sollte --Harmonie
um den ES6-Modus zu aktivieren. Schließlich geben wir auch den Ort aller Tests an. EIN Makefile
kann für das endlose Testen Ihrer Anwendung konfiguriert werden.
Um Ihre App zu testen, verwenden Sie einfach den folgenden Befehl im Hauptverzeichnis der Anwendung.
$ test machen
Denken Sie daran, vor dem Testen mit dem folgenden Befehl Testmodule zu installieren (Mocha sollte, Supertest):
$ npm install mocha sollte mocha --save-dev sein
Um unsere Anwendungen in der Produktion zu betreiben, verwenden wir PM2, einen nützlichen Node-Prozessmonitor. Wir sollten die Logger-App während der Produktion deaktivieren. Es kann mit Umgebungsvariablen automatisiert werden.
Um PM2 zu installieren, geben Sie im Terminal den folgenden Befehl ein
$ npm install pm2 -g
Und unsere App kann mit dem folgenden Befehl gestartet werden:
$ pm2 start index.js --node-args = "- Harmonie"
Selbst wenn unsere Anwendung abstürzt, wird sie automatisch neu gestartet und Sie können ruhig schlafen.
Koa ist eine leichte und ausdrucksstarke Middleware für Node.js, die das Schreiben von Webanwendungen und APIs noch angenehmer macht.
Sie können eine Vielzahl von Community-Modulen nutzen, um die Funktionalität Ihrer Anwendung zu erweitern und alle alltäglichen Aufgaben zu vereinfachen, wodurch die Webentwicklung zu einer lustigen Aktivität wird.
Bitte zögern Sie nicht, Kommentare, Fragen oder andere Informationen in das Feld unten zu schreiben.