Heim >Web-Frontend >js-Tutorial >Lassen Sie Express die gemeinsame Nutzung asynchroner Methoden unterstützen
In diesem Artikel wird hauptsächlich detailliert beschrieben, wie man die Express-Unterstützung asynchron/wartet. Der Herausgeber findet es ziemlich gut, daher werde ich es jetzt mit Ihnen teilen und als Referenz geben. Folgen wir dem Herausgeber und schauen wir uns das an. Ich hoffe, es kann allen helfen.
Mit der Veröffentlichung von Node.js v8 hat Node.js nativ Async/Await-Funktionen unterstützt, und das Web-Framework Koa hat auch die offizielle Version von Koa 2 veröffentlicht, die Async/Await-Middleware unterstützt Die Handhabung asynchroner Rückrufe bietet großen Komfort.
Da Koa 2 bereits Async/Await-Middleware unterstützt, warum nicht Koa direkt verwenden, aber auch Express ändern, um Async/Await-Middleware zu unterstützen? Da die offizielle Version von Koa 2 vor nicht allzu langer Zeit veröffentlicht wurde und viele alte Projekte immer noch Express verwenden, ist es unmöglich, sie zu stürzen und in Koa neu zu schreiben. Diese Kosten sind zu hoch, aber wenn Sie den Komfort nutzen möchten Mit der neuen Syntax können Sie nur Express transformieren, und diese Transformation darf das Unternehmen nicht beeinträchtigen, da sie sonst große Probleme verursacht.
Async/await direkt verwenden
Lassen Sie uns zunächst einen Blick auf die Situation der direkten Verwendung der async/await-Funktion in Express werfen.
const express = require('express'); const app = express(); const { promisify } = require('util'); const { readFile } = require('fs'); const readFileAsync = promisify(readFile); app.get('/', async function (req, res, next){ const data = await readFileAsync('./package.json'); res.send(data.toString()); }); // Error Handler app.use(function (err, req, res, next){ console.error('Error:', err); res.status(500).send('Service Error'); }); app.listen(3000, '127.0.0.1', function (){ console.log(`Server running at http://${this.address().address }:${this.address().port }/`); });
Das Obige verändert Express nicht und verwendet direkt die Funktion async/await, um die Anfrage zu verarbeiten. Bei der Anforderung von http://127.0.0.1:3000/ wird festgestellt, dass die Anfrage angefordert werden kann normal und die Reaktion kann auch „Normale Reaktion“ sein. Es scheint, dass Sie die Funktion „async/await“ direkt verwenden können, ohne Änderungen an Express vorzunehmen. Wenn jedoch ein Fehler in der Funktion „async/await“ auftritt, kann dieser von unserer Fehlerbehandlungs-Middleware behandelt werden? Lassen Sie uns nun eine nicht vorhandene Datei lesen und beispielsweise die zuvor gelesene Datei package.json durch age.json ersetzen.
app.get('/', async function (req, res, next){ const data = await readFileAsync('./age.json'); res.send(data.toString()); });
Wenn wir jetzt http://127.0.0.1:3000/ anfordern, stellen wir fest, dass die Anfrage nur langsam reagiert und irgendwann eine Zeitüberschreitung auftritt. Der folgende Fehler wurde im Terminal gemeldet:
Es wurde festgestellt, dass der Fehler nicht von der Fehlerbehandlungs-Middleware behandelt wurde, sondern eine unhandledRejection-Ausnahme ausgelöst wurde try/catch, um Fehler manuell abzufangen?
app.get('/', async function (req, res, next){ try { const data = await readFileAsync('./age.json'); res.send(datas.toString()); } catch(e) { next(e); } });
Es wurde festgestellt, dass die Anfrage von der Fehlerbehandlungs-Middleware verarbeitet wird, was bedeutet, dass es für uns in Ordnung ist, den Fehler manuell und explizit zu erfassen, aber wenn wir jeder Middleware einen Try/Catch hinzufügen oder Anforderungsverarbeitungsfunktion, es wird auch Es ist zu unelegant, es stört den Geschäftscode und der Code sieht hässlich aus. Daher haben wir durch Experimente mit der direkten Verwendung von Async/Await-Funktionen herausgefunden, dass die Richtung der Transformation von Express darin besteht, Fehler zu empfangen, die in Async/Await-Funktionen ausgelöst werden, ohne den Geschäftscode zu beeinträchtigen.
Express ändern
Es gibt zwei Möglichkeiten, Routing und Middleware in Express zu verwalten. Eine besteht darin, eine App über Express zu erstellen, Middleware hinzuzufügen und das Routing direkt in der App zu verwalten, wie folgt:
const express = require('express'); const app = express(); app.use(function (req, res, next){ next(); }); app.get('/', function (req, res, next){ res.send('hello, world'); }); app.post('/', function (req, res, next){ res.send('hello, world'); }); app.listen(3000, '127.0.0.1', function (){ console.log(`Server running at http://${this.address().address }:${this.address().port }/`); });
Die andere besteht darin, eine Routing-Instanz über den Router von Express zu erstellen und das Routing direkt auf der Routing-Instanz zu verarbeiten, wie folgt:
const express = require('express'); const app = express(); const router = new express.Router(); app.use(router); router.get('/', function (req, res, next){ res.send('hello, world'); }); router.post('/', function (req, res, next){ res.send('hello, world'); }); app.listen(3000, '127.0.0.1', function (){ console.log(`Server running at http://${this.address().address }:${this.address().port }/`); });
Dies ist möglich gemischt. Lassen Sie uns nun darüber nachdenken, wie man eine Funktion wie app.get('/', async function(req, res, next){}) erstellt, damit die darin enthaltene asynchrone Funktion einen Fehler auslöst. Damit Fehler einheitlich behandelt werden können, muss natürlich next(err) aufgerufen werden, um den Fehler an die Fehlerbehandlungs-Middleware zu übergeben. Da die async-Funktion ein Promise zurückgibt, muss es in der Form asyncFn().then( vorliegen. ).catch. (function(err){ next(err) }), wenn Sie es also so ändern, erhalten Sie den folgenden Code:
app.get = function (...data){ const params = []; for (let item of data) { if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') { params.push(item); continue; } const handle = function (...data){ const [ req, res, next ] = data; item(req, res, next).then(next).catch(next); }; params.push(handle); } app.get(...params) }
Im obigen Code bestimmen wir die App .get()-Funktion Wenn unter den Parametern eine asynchrone Funktion vorhanden ist, verwenden Sie item(req, res, next).then(next).catch(next);, um sie zu verarbeiten, damit in der Funktion ausgelöste Fehler erfasst werden können und an die Fehlerbehandlungs-Middleware Go inside übergeben. Es gibt jedoch einen offensichtlichen Fehler in diesem Code. Er ruft am Ende app.get() auf, was rekursiv ist, die Funktion von app.get zerstört und die Anfrage überhaupt nicht verarbeiten kann, sodass er weiterhin geändert werden muss .
Wir haben zuvor gesagt, dass die beiden Methoden von Express zur Handhabung von Routing und Middleware gemischt werden können, daher werden wir diese beiden Methoden mischen, um Rekursionen zu vermeiden:
const express = require('express'); const app = express(); const router = new express.Router(); app.use(router); app.get = function (...data){ const params = []; for (let item of data) { if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') { params.push(item); continue; } const handle = function (...data){ const [ req, res, next ] = data; item(req, res, next).then(next).catch(next); }; params.push(handle); } router.get(...params) }
Reform ähnlich oben Danach schien alles gut zu funktionieren und Anfragen wurden normal bearbeitet. Als ich mir jedoch den Quellcode von Express ansah, stellte ich fest, dass dadurch die Methode app.get() zerstört wurde, da app.get() nicht nur das Routing verarbeiten, sondern auch die Anwendungskonfiguration abrufen kann wie folgt:
methods.forEach(function(method){ app[method] = function(path){ if (method === 'get' && arguments.length === 1) { // app.get(setting) return this.set(path); } this.lazyrouter(); var route = this._router.route(path); route[method].apply(route, slice.call(arguments, 1)); return this; }; });
Während der Transformation müssen wir also auch eine spezielle Verarbeitung für app.get durchführen. In tatsächlichen Anwendungen haben wir nicht nur Get-Anfragen, sondern auch Post-, Put- und Delete-Anfragen, sodass der Code, den wir schließlich transformiert haben, wie folgt lautet:
const { promisify } = require('util'); const { readFile } = require('fs'); const readFileAsync = promisify(readFile); const express = require('express'); const app = express(); const router = new express.Router(); const methods = [ 'get', 'post', 'put', 'delete' ]; app.use(router); for (let method of methods) { app[method] = function (...data){ if (method === 'get' && data.length === 1) return app.set(data[0]); const params = []; for (let item of data) { if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') { params.push(item); continue; } const handle = function (...data){ const [ req, res, next ] = data; item(req, res, next).then(next).catch(next); }; params.push(handle); } router[method](...params); }; } app.get('/', async function (req, res, next){ const data = await readFileAsync('./package.json'); res.send(data.toString()); }); app.post('/', async function (req, res, next){ const data = await readFileAsync('./age.json'); res.send(data.toString()); }); router.use(function (err, req, res, next){ console.error('Error:', err); res.status(500).send('Service Error'); }); app.listen(3000, '127.0.0.1', function (){ console.log(`Server running at http://${this.address().address }:${this.address().port }/`); });
Jetzt ist die Transformation abgeschlossen, wir müssen nur noch hinzufügen Mit einem kleinen Codeteil können Sie die Async-Funktion direkt als Handler verwenden, um die Anforderung zu verarbeiten, was für das Unternehmen nicht aufdringlich ist, und die ausgegebenen Fehler können auch an die Fehlerbehandlungs-Middleware übergeben werden.
Verwandte Empfehlungen:
Wie NodeJs die asynchrone Verarbeitung durch Async und Wait handhabt
So verwenden Sie asynchrone Funktionen in Node. js
Detaillierte Erläuterung der async+await-Synchronisations-/asynchronen Lösung von ES6
Das obige ist der detaillierte Inhalt vonLassen Sie Express die gemeinsame Nutzung asynchroner Methoden unterstützen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!