Verwandte Empfehlungen: „nodejs Tutorial“
Apropos Middleware: Viele Entwickler werden an Koa.js denken, und sein Middleware-Design ist zweifellos einer der typischen Vertreter des Front-End-Middleware-Denkens.
Als ich diesen Teil des Inhalts kürzlich überprüft habe, konnte ich nicht anders, als mit euch Lesern über seine Wunderbarkeit zu plaudern!
Koa ist sehr benutzerfreundlich – im Vergleich zu Express wirken die Funktionen aufgrund des „perfekten Middleware“-Designs sehr einfach! Der Autor hat dies im Projekt verwendet:
const Koa=require('koa') const app=new Koa() const Router=require('koa-router') const router=new Router() const cors=require('koa2-cors') const koaBody=require('koa-body') const ENV='test-mpin2' app.use(cors({ origin:['http://localhost:9528'], // 也可以写为:['*'] credentials:true })) app.use(koaBody({ multipart:true })) app.use(async(ctx,next)=>{ console.log('访问全局中间件') ctx.state.env=ENV // 全局缓存 await next() }) const playlist=require('./controller/playlist.js') router.use('/playlist',playlist.routes()) const blog=require('./controller/blog.js') router.use('/blog',blog.routes()) app.use(router.routes()).use(router.allowedMethods()) app.listen(3000,()=>{ console.log('服务已开启') })
Es extrahiert den Routing-Router und verwendet ihn als separate Middleware, und die App ist nur für die globale Verarbeitung verantwortlich. Ein weiteres Beispiel:
// 最外层中间件,可以用于兜底 Koa 全局错误 app.use(async (ctx, next) => { try { // 执行下一个中间件 await next(); } catch (error) { console.log(`[koa error]: ${error.message}`) } }); // 第二层中间件,可以用于日志记录 app.use(async (ctx, next) => { const { req } = ctx; console.log(`req is ${JSON.stringify(req)}`); await next(); console.log(`res is ${JSON.stringify(ctx.res)}`); });
Ein Koa einfach umzusetzen!
Wie im obigen Code gezeigt, schauen wir uns die Koa-Instanz an und registrieren und verketten die Middleware über die use-Methode. Die einfache Implementierung des Quellcodes kann ausgedrückt werden als:
use(fn) { this.middleware.push(fn); return this; }
Wir speichern die Middleware im this.middleware
array , also wie wird die Middleware ausgeführt? Sehen Sie sich den Quellcode unten an: this.middleware
数组中,那么中间件是如何被执行的呢?参考下面源码:
// 通过 createServer 方法启动一个 Node.js 服务 listen(...args) { const server = http.createServer(this.callback()); server.listen(...args); }
Koa 框架通过 http 模块的 createServer
方法创建一个 Node.js 服务,并传入 this.callback()
方法, callback源码简单实现如下:
callback(){ const fn=compose(this.middlewareList) return (req,res)=>{ const ctx=createContext(req,res) return this.handleRequest(ctx,fn) } } handleRequest(ctx, fn) { const onerror = err => ctx.onerror(err); // 将 ctx 对象传递给中间件函数 fn return fn(ctx).catch(onerror); }
如上代码,我们将 Koa 一个中间件组合和执行流程梳理为以下步骤:
通过一个方法(我们称为compose)组合各种中间件,返回一个中间件组合函数
fn
-
请求过来时,会先调用
handleRequest
方法,该方法完成:- 调用
createContext
方法,对该次请求封装出一个ctx对象; - 接着调用
this.handleRequest(ctx, fn)
处理该次请求。
- 调用
其中,核心过程就是使用compose方法组合各种中间件 —— 这是一个单独的方法,它应该不受Koa其余方法的约束。其源码简单实现为:
// 组合中间件 // 和express中的next函数意义一样 function compose(middlewareList){ // return function意思是返回一个函数 return function(ctx,next){ // 各种中间件调用的逻辑 function dispatch(i){ const fn=middlewareList[i] || next if(fn){ try{ // koa中都是async,其返回的是一个promise(对象) return Promise.resolve(fn(ctx,function next(){ return dispatch(i+1) })) }catch(err){ return Promise.reject(err) } }else{ return Promise.resolve() } } return dispatch(0) } }
其功能可以表示为这样(非源码):
async function middleware1() { //... await (async function middleware2() { //... await (async function middleware3() { //... }); //... }); //... }
到这里我们其实可以“初窥”其原理,有两点:
- Koa 的中间件机制被社区形象地总结为洋葱模型;
所谓洋葱模型,就是指每一个 Koa 中间件都是一层洋葱圈,它即可以掌管请求进入,也可以掌管响应返回。换句话说:外层的中间件可以影响内层的请求和响应阶段,内层的中间件只能影响外层的响应阶段。
- dispatch(n)对应第 n 个中间件的执行,在使用中即第 n 个中间件可以通过await next()来“插入”执行下一个中间件,同时在最后一个中间件执行完成后,依然有恢复执行的能力。即:通过洋葱模型,await next()控制调用后面的中间件,直到全局没有可执行的中间件且堆栈执行完毕,最终“原路返回”至第一个执行next的中间件。这种方式有个优点,特别是对于日志记录以及错误处理等全局功能需要非常友好。
Koa1 的中间件实现利用了 Generator 函数 + co 库(一种基于 Promise 的 Generator 函数流程管理工具),来实现协程运行。本质上,Koa v1 中间件和 Koa v2 中间件思想是类似的,只不过 Koa v2 改用了 Async/Await 来替换 Generator 函数 + co 库,整体实现更加巧妙,代码更加优雅。—— from《狼书》
经过上述部分源码的描述,我们就可以采用es6的方式将其组合起来:
// myKoa.js文件 const http=require('http') function compose(){} //见上 class LikeKoa2{ constructor() { this.middlewareList=[] } use(){} //见上 // 把所有的req,res属性、事件都交给ctx(这里只是简写) createContext(req,res){ const ctx={ req, res } // 比如 ctx.query=req,query return ctx } handleRequest(){} //见上 callback(){} //见上 listen(){} //见上 } // koa和express的不同之一: // express在调用时直接调用函数:const app=express();所以暴露出去new过的对象——具体见下面链接中代码 // 但是koa调用时以类的方式:const app=new Koa();所以直接暴露出去 module.exports=LikeKoa2
那use方法和其余方法并不相通,它是如何被执行的呢?执行了createServer后是不是相当于建立了一个通道、挂载了一个监听函数呢?
这一点恐怕就要到Node的源码中一探究竟了…
对比 Koa,聊聊 Express 原理
说起 Node.js 框架,我们一定忘不了 Express —— 不同于 Koa,它继承了路由、静态服务器和模板引擎等功能,虽然比之Koa显得“臃肿”了许多,但看上去比 Koa 更像是一个框架。通过学习 Express 源码,笔者简单的总结了它的工作机制:
通过app.use方法注册中间件。
一个中间件可以理解为一个 Layer 对象,其中包含了当前路由匹配的正则信息以及 handle 方法。
所有中间件(Layer 对象)使用stack数组存储起来。
当一个请求过来时,会从 req 中获取请求 path,根据 path 从stack中找到匹配的 Layer,具体匹配过程由
router.handle
函数实现。-
router.handle
函数通过next()
((req, res) => { console.log('第一个中间件'); ((req, res) => { console.log('第二个中间件'); (async(req, res) => { console.log('第三个中间件'); await sleep(2000) res.status(200).send('hello') })(req, res) console.log('第二个中间件调用结束'); })(req, res) console.log('第一个中间件调用结束') })(req, res)
Das Koa-Framework erstellt einen Node.js-Dienst über die MethodecreateServer
des http-Moduls und übergibt den Codethis.callback() >-Methode. Der Callback-Quellcode wird einfach wie folgt implementiert: 🎜rrreee🎜Wie im Code oben gezeigt, organisieren wir die Koa-Middleware-Kombination und den Ausführungsprozess in die folgenden Schritte: 🎜<ul style="list-style-type: disc;"> <li>🎜Durch eine Methode (wir nennen sie compose) werden verschiedene Middleware-Funktionen kombiniert und eine Middleware-Kombinationsfunktion zurückgegeben <code>fn
🎜 - 🎜Wenn eine Anfrage kommt, wird die handleRequest
- Rufen Sie die Methode
createContext
auf, um ein ctx-Objekt für diese Anfrage zu kapseln >Dann rufen Siethis.handleRequest(ctx, fn)
auf. Verarbeiten Sie die Anfrage.
- Koas Middleware Der Mechanismus wird von der Community anschaulich als Zwiebelmodell zusammengefasst
🎜Das sogenannte Zwiebelmodell bedeutet, dass jede Koa-Middleware eine Schicht aus Zwiebelringen ist , das sowohl den Anforderungseintrag als auch die zurückgegebene Antwort verarbeiten kann. Mit anderen Worten: Die äußere Middleware kann die Anforderungs- und Antwortphasen der inneren Schicht beeinflussen, und die innere Middleware kann nur die Antwortphase der äußeren Schicht beeinflussen. 🎜
- dispatch(n) entspricht der Ausführung der n-ten Middleware. Bei Verwendung kann die n-te Middleware über „await next()“ „eingefügt“ werden, um die nächste Middleware auszuführen gleichzeitig Nachdem die letzte Middleware-Ausführung abgeschlossen ist, besteht immer noch die Möglichkeit, die Ausführung fortzusetzen. Das heißt: Über das Zwiebelmodell steuert das Warten auf next () den Aufruf nachfolgender Middleware, bis global keine ausführbare Middleware mehr vorhanden ist und der Stapel ausgeführt wird, und kehrt schließlich zum ursprünglichen Pfad zur ersten Middleware zurück, die als nächstes ausgeführt wird. Dieser Ansatz hat Vorteile, insbesondere für globale Funktionen wie Protokollierung und Fehlerbehandlung, die sehr benutzerfreundlich sein müssen.
🎜Koa1s Middleware-Implementierung verwendet die Generator-Funktion + Co-Bibliothek (ein auf Promise basierendes Prozessmanagement-Tool für Generatorfunktionen), um den Coroutine-Betrieb zu implementieren. Im Wesentlichen sind die Ideen der Koa v1-Middleware und der Koa v2-Middleware ähnlich, mit der Ausnahme, dass Koa v2 Async/Await verwendet, um die Generator-Funktion + die Co-Bibliothek zu ersetzen. Die Gesamtimplementierung ist cleverer und der Code eleganter. —— aus „Wolf Book“ 🎜🎜Nachdem wir den obigen Teil des Quellcodes beschrieben haben, können wir ihn mit es6 kombinieren: 🎜rrreee🎜Die Verwendungsmethode ist nicht mit anderen Methoden verbunden. Wie wird sie ausgeführt? ? Entspricht die Ausführung von createServer dem Einrichten eines Kanals und dem Mounten einer Abhörfunktion?
Ich fürchte, wir müssen mehr darüber im Quellcode von Node herausfinden ... 🎜🎜🎜🎜Im Vergleich zu Koa sprechen wir über das Prinzip von Express🎜🎜🎜Apropos Node.js-Framework , wir dürfen Express nicht vergessen – im Gegensatz zu Koa erbt es Funktionen wie Routing, statischen Server und Template-Engine. Obwohl es viel „aufgedunsen“ ist als Koa, ähnelt es eher einem Framework als Koa. Durch das Studium des Express-Quellcodes fasste der Autor einfach seinen Arbeitsmechanismus zusammen: 🎜
- 🎜Middleware über die app.use-Methode registrieren. 🎜
- 🎜Eine Middleware kann als Layer-Objekt verstanden werden, das die regulären Informationen enthält, die mit der aktuellen Route und der Handle-Methode übereinstimmen. 🎜
- 🎜Alle Middleware (Layer-Objekte) werden mithilfe des Stack-Arrays gespeichert. 🎜
- 🎜Wenn eine Anfrage eingeht, wird der Anfragepfad von req abgerufen und die passende Ebene wird entsprechend dem Pfad aus dem Stapel gefunden. Der spezifische Matching-Prozess wird durch den
implementiert router.handle
-Funktion. 🎜 - 🎜Die Funktion
router.handle
durchläuft jede Ebene zum Vergleich mit der Methodenext()
: 🎜-
next()
方法通过闭包维持了对于 Stack Index 游标的引用,当调用next()
方法时,就会从下一个中间件开始查找; - 如果比对结果为 true,则调用
layer.handle_request
方法,layer.handle_request
方法中会调用next()方法 ,实现中间件的执行。
-
通过上述内容,我们可以看到,Express 其实是通过 next()
方法维护了遍历中间件列表的 Index 游标,中间件每次调用next()
方法时,会通过增加 Index 游标的方式找到下一个中间件并执行。它的功能就像这样:
((req, res) => { console.log('第一个中间件'); ((req, res) => { console.log('第二个中间件'); (async(req, res) => { console.log('第三个中间件'); await sleep(2000) res.status(200).send('hello') })(req, res) console.log('第二个中间件调用结束'); })(req, res) console.log('第一个中间件调用结束') })(req, res)
如上代码,Express 中间件设计并不是一个洋葱模型,它是基于回调实现的线形模型,不利于组合,不利于互操,在设计上并不像 Koa 一样简单。而且业务代码有一定程度的侵扰,甚至会造成不同中间件间的耦合。
express的简单实现笔者已上传至腾讯微云,需要者可自行查看&下载:express的简单实现
更多编程相关知识,请访问:编程视频!!
Das obige ist der detaillierte Inhalt vonVergleichen Sie die NodeJS-Middleware Koa und Express. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

node、nvm与npm的区别:1、nodejs是项目开发时所需要的代码库,nvm是nodejs版本管理工具,npm是nodejs包管理工具;2、nodejs能够使得javascript能够脱离浏览器运行,nvm能够管理nodejs和npm的版本,npm能够管理nodejs的第三方插件。

Vercel是什么?本篇文章带大家了解一下Vercel,并介绍一下在Vercel中部署 Node 服务的方法,希望对大家有所帮助!

node怎么爬取数据?下面本篇文章给大家分享一个node爬虫实例,聊聊利用node抓取小说章节的方法,希望对大家有所帮助!

node导出模块的两种方式:1、利用exports,该方法可以通过添加属性的方式导出,并且可以导出多个成员;2、利用“module.exports”,该方法可以直接通过为“module.exports”赋值的方式导出模块,只能导出单个成员。

安装node时会自动安装npm;npm是nodejs平台默认的包管理工具,新版本的nodejs已经集成了npm,所以npm会随同nodejs一起安装,安装完成后可以利用“npm -v”命令查看是否安装成功。

node中没有包含dom和bom;bom是指浏览器对象模型,bom是指文档对象模型,而node中采用ecmascript进行编码,并且没有浏览器也没有文档,是JavaScript运行在后端的环境平台,因此node中没有包含dom和bom。

本篇文章带大家聊聊Node.js中的path模块,介绍一下path的常见使用场景、执行机制,以及常用工具函数,希望对大家有所帮助!


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Dreamweaver Mac
Visuelle Webentwicklungstools

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

SAP NetWeaver Server-Adapter für Eclipse
Integrieren Sie Eclipse mit dem SAP NetWeaver-Anwendungsserver.

Sicherer Prüfungsbrowser
Safe Exam Browser ist eine sichere Browserumgebung für die sichere Teilnahme an Online-Prüfungen. Diese Software verwandelt jeden Computer in einen sicheren Arbeitsplatz. Es kontrolliert den Zugriff auf alle Dienstprogramme und verhindert, dass Schüler nicht autorisierte Ressourcen nutzen.

VSCode Windows 64-Bit-Download
Ein kostenloser und leistungsstarker IDE-Editor von Microsoft
