Compare nodejs middleware Koa and Express
Related recommendations: "nodejs Tutorial"
Speaking of middleware, many developers will think of Koa.js, and its middleware design is undoubtedly It is one of the typical representatives of front-end middleware thinking.
Recently reviewing this part of the content, I couldn’t help but want to chat with you readers about its wonderfulness!
Koa is very convenient to use - compared to express, its "perfect middleware" design makes the functions look very simple! The author has used it like this in the project:
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('服务已开启') })
It extracts the routing router and uses it as a separate middleware, and the app is only responsible for global processing. Another example:
// 最外层中间件,可以用于兜底 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)}`); });
Simply implement a Koa!
As shown in the above code, we look at the Koa instance and register and concatenate the middleware through the use method. The simple implementation of the source code can be expressed as:
use(fn) { this.middleware.push(fn); return this; }
We store the middleware in this.middleware
In the array, how is the middleware executed? Refer to the source code below:
// 通过 createServer 方法启动一个 Node.js 服务 listen(...args) { const server = http.createServer(this.callback()); server.listen(...args); }
Koa framework creates a Node.js service through the createServer
method of the http module, and passes in the this.callback()
method, callback source code The simple implementation is as follows:
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); }
As shown in the above code, we organize the Koa middleware combination and execution process into the following steps:
Through a method (we call it compose) Combine various middleware and return a middleware combination function
fn
When a request comes, the
handleRequest
method will be called first, and the method is completed :- Call the
createContext
method to encapsulate a ctx object for this request; - then call
this.handleRequest(ctx, fn)
Process this request.
- Call the
The core process is to use the compose method to combine various middlewares - this is a separate method, and it should not be constrained by the rest of Koa's methods. Its source code is simply implemented as:
// 组合中间件 // 和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) } }
Its function can be expressed as follows (non-source code):
async function middleware1() { //... await (async function middleware2() { //... await (async function middleware3() { //... }); //... }); //... }
At this point we can actually get a "first glimpse" of its principle, there are two points:
- Koa’s middleware mechanism is vividly summarized by the community as an onion model;
The so-called onion model means that each Koa middleware is a layer of onion rings. It can handle both request entry and response return. In other words: the outer middleware can affect the request and response phases of the inner layer, and the inner middleware can only affect the response phase of the outer layer.
- dispatch(n) corresponds to the execution of the nth middleware. When in use, the nth middleware can be "inserted" to execute the next middleware through await next(). At the same time, after the execution of the last middleware is completed, there is still the ability to resume execution. That is: through the onion model, await next() controls the calling of subsequent middleware until there is no executable middleware in the world and the stack execution is completed, and finally "returns to the original path" to the first middleware that executes next. This method has advantages, especially for global functions such as logging and error handling that need to be very friendly.
Koa1’s middleware implementation uses the Generator function co library (a Generator function process management tool based on Promise) to implement coroutine running. In essence, the ideas of Koa v1 middleware and Koa v2 middleware are similar, except that Koa v2 uses Async/Await to replace the Generator function co library. The overall implementation is more clever and the code is more elegant. —— from "Wolf Book"
After describing the above part of the source code, we can combine it using 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
The use method is not the same as other methods. Interlinked, how is it executed? After executing createServer, is it equivalent to establishing a channel and mounting a listening function?
I’m afraid we need to find out more about this in the source code of Node...
Compare Koa and talk about the principles of Express
Speaking of Node. js framework, we must not forget Express - unlike Koa, it inherits functions such as routing, static server and template engine. Although it is much "bloated" compared to Koa, it looks more like a framework than Koa. By studying the Express source code, the author simply summarized its working mechanism:
Register middleware through the app.use method.
A middleware can be understood as a Layer object, which contains the regular information matched by the current route and the handle method.
All middleware (Layer objects) are stored using the stack array.
When a request comes, the request path will be obtained from req, and the matching Layer will be found from the stack according to the path. The specific matching process is performed by the
router.handle
function accomplish.router.handle
The function traverses each layer for comparison through thenext()
method: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的简单实现
更多编程相关知识,请访问:编程视频!!
The above is the detailed content of Compare nodejs middleware Koa and Express. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



How to delete node with nvm: 1. Download "nvm-setup.zip" and install it on the C drive; 2. Configure environment variables and check the version number through the "nvm -v" command; 3. Use the "nvm install" command Install node; 4. Delete the installed node through the "nvm uninstall" command.

How to handle file upload? The following article will introduce to you how to use express to handle file uploads in the node project. I hope it will be helpful to you!

This article will share with you Node's process management tool "pm2", and talk about why pm2 is needed, how to install and use pm2, I hope it will be helpful to everyone!

Detailed explanation and installation guide for PiNetwork nodes This article will introduce the PiNetwork ecosystem in detail - Pi nodes, a key role in the PiNetwork ecosystem, and provide complete steps for installation and configuration. After the launch of the PiNetwork blockchain test network, Pi nodes have become an important part of many pioneers actively participating in the testing, preparing for the upcoming main network release. If you don’t know PiNetwork yet, please refer to what is Picoin? What is the price for listing? Pi usage, mining and security analysis. What is PiNetwork? The PiNetwork project started in 2019 and owns its exclusive cryptocurrency Pi Coin. The project aims to create a one that everyone can participate

How to package nodejs executable file with pkg? The following article will introduce to you how to use pkg to package a Node project into an executable file. I hope it will be helpful to you!

npm node gyp fails because "node-gyp.js" does not match the version of "Node.js". The solution is: 1. Clear the node cache through "npm cache clean -f"; 2. Through "npm install -g n" Install the n module; 3. Install the "node v12.21.0" version through the "n v12.21.0" command.

What is a single sign-on system? How to implement it using nodejs? The following article will introduce to you how to use node to implement a single sign-on system. I hope it will be helpful to you!

Authentication is one of the most important parts of any web application. This tutorial discusses token-based authentication systems and how they differ from traditional login systems. By the end of this tutorial, you will see a fully working demo written in Angular and Node.js. Traditional Authentication Systems Before moving on to token-based authentication systems, let’s take a look at traditional authentication systems. The user provides their username and password in the login form and clicks Login. After making the request, authenticate the user on the backend by querying the database. If the request is valid, a session is created using the user information obtained from the database, and the session information is returned in the response header so that the session ID is stored in the browser. Provides access to applications subject to
