3rd Day

中间件

  • 页面发送请求,经过中间件,到服务器;服务器再将响应传回页面
  • 中间件相当于黑箱操作,在箱子里经过一系列的函数操作,到达目的地,也可以在进行某个中间件操作的时候判断是否符合条件,可以调至下一个中间件或直接到终点

利用中间件构建一个简易Express

路由的匹配

1
2
3
4
5
6
7
8
9
10
11
12
var isMatch = (reqUrl, targetPath) => {
var targets = targetPath.split('/').filter(e => e != '');
return url.parse(reqUrl).pathname.split('/').filter(e => e != '').every((subUrl, idx) => {
if (idx >= targets.length){
return true;
} else {
return subUrl === targets[idx]
}
});
}
  • 利用箭头函数传入参数,用split和filter把空格和‘/’去掉,然后请求路由和目标路由匹配

封装500

1
2
3
4
5
6
7
8
9
10
function res500(res){
res.writeHead(500, {
"Content-Type": "text/html"
})
res.end(`500! <h1>Timeout</h1>`);
}
var timer = setTimeout(function(){
res500(res);
}, 3000);
  • 设置500和超时,超过3S没响应就报错

精髓

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
var targetPath = wares[0].path;
if (!wares[1]){
// 后继不存在
// wares[0](req, res, res404);
if (targetPath){
if (isMatch(req.url, targetPath)) wares[0](req, res, res404);
} else {
wares[0](req, res, res404);
}
} else {
// 后继确实存在
// 如果是路由模块
if (targetPath){
if (isMatch(req.url, targetPath)){
// 路径匹配成功 执行之
wares[0](req, res, function(){
clearTimeout(timer);
// wares[1]();
goThrough(req, res, wares.slice(1));
});
} else {
// 匹配失败 跳过
goThrough(req, res, wares.slice(1));
}
} else {
// 不是路由模块 原路执行
wares[0](req, res, function(){
clearTimeout(timer);
// wares[1]();
goThrough(req, res, wares.slice(1));
});
}
}
}
  • 首先将中间件路由作为数组传进targetPath,ware是设置好的中间件,类似一个数组
  • 因为使用了一次ware后都会slice除去第0个中间件,所以需要判断下一个中间件还存不存在
  • 将页面传来的url和中间件路由匹配(通过判断targetPath是否存在来判断是不是路由模块)

实现调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function getHTTPServer(http){
var app = http.createServer(function(req, res){
var i = 0;
goThrough(req, res, midWares);
});
app.use = function(midWare){
midWares.push(midWare);
}
app.route = function(path, midWare){
midWare.path = path;
midWares.push(midWare);
}
return app;
}
  • 创建一个服务器