express手写

执行代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
let express = require('./index.js')
let app = express();
// 参数不写就是 /
app.use(function(req,res,next){
console.log('middleware')
res.setHeader('Content-Type','text/html;charset=utf-8')
next('name error')
})

app.get('/name',function(req,res){
res.end('name')
})

app.all('*',function(req,res){
res.end('all')
})
app.use(function(err,req,res,next){
console.log(err)
next(err)
})
app.use(function(err,req,res,next){
console.log(err+' 2')
next()
})
app.post('/age',function(req,res){
res.end('age')
})
app.listen(3001,function(){
console.log('server start 3001')
})

手写代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
let http = require('http');
let url = require('url')
function createApplication(){
// app 是一个监听函数
let app = (req,res)=>{
// 取出每一个layer
// 1.获取请求的方法
let m = req.method.toLowerCase();
let { pathname } = url.parse(req.url,true)
let index = 0;
// 递归
function next(err){
// 数组全部迭代完毕还没有找到,说明路径不存在
if(index === app.routes.length){
return res.end(`Cannot find ${m} ${pathname}`)
}
let {method, path, handler} = app.routes[index++]
if(err){
// 如果有错误 我们应该去找错误中间件,错误中间件有四个参数
if(handler.length === 4){
handler(err,req,res,next)
} else {
// 如果没有匹配到,要将error继续传递下去
next(err)
}
} else {
if(method === 'middle'){
if(path === '/' || path === pathname || pathname.startsWith(path+'/')){
handler(req,res,next);
} else {
next(); // 如果这个中间件没有匹配到,继续走下一个
}
} else {
if(
(method === m || method === 'all') &&
(path === pathname || path === '*')
){
handler(req,res)
} else {
next();
}
}
}

}
next();
}
// 路径是一个数组
app.routes = [];
app.use = function(path,handler){
if(typeof handler !== 'function'){
handler = path;
path ='/'
}
let layer = {
method:'middle',
path,
handler
}
app.routes.push(layer)
}
app.all = function(path,handler){
let layer = {
method:'all',
path,
handler
}
app.routes.push(layer)
}
http.METHODS.forEach(method=>{
method = method.toLocaleLowerCase();
app[method] = function(path,handler){
let layer = {
method,
path,
handler
}
app.routes.push(layer)
}
})
app.listen = function(){
let server = http.createServer(app)
server.listen(...arguments)
}
return app;
}
module.exports = createApplication

express 基本规则

1. 路由匹配(app.getapp.post …),app.all 全路由匹配
2. app.use(path,handler) 中间件匹配,只有handlerpath默认为 /
3. 中间件用next执行下一个中间件,next一旦传入信息则会去寻找错误中间件
错误中间件有4个参数

express 总结

  1. express中间件和路由按顺序放入routes,
  2. 当执行中间件的时候,会传递next,使得下一个中间件或者路由得以执行
  3. 当执行到路由的时候就不会传递next,也使得routes的遍历提前结束
  4. 当执行完错误中间件后,会继续执行后面的中间件和路由

express手写
http://arch94.github.io/2023/08/27/express手写/
作者
Arch Sun
发布于
2023年8月27日
许可协议