功能演進:
V1:
*基礎http服務器
*支持中間件
*支持異步中間件
V1.X:
*JS切換爲TS
*request/respone裝飾增強
*異常處理
*細化流程控制
V2:
*AOP自定義註解攔截
*IOC管理注入@Controller/@Service組件
*@Request標記handler
*@ResponseBody自動處理返回值
V1:
SOS.js
const http = require('http');
const url = require('url');
//合併中間件
const compose = (ctx) => (...funcs) => {
if (funcs.length === 0) {
return arg => arg
}
let lastIndex = funcs.length - 1;
return funcs.reduceRight((a, b,index) => b(() => {
if(index === funcs.length - 1){
return Promise.resolve();
}
//判斷是否重複調用next()
if(lastIndex !== index){
return Promise.reject(new Error('can not call next() over once!'))
}
lastIndex--;
try{
return Promise.resolve(a(ctx));
}catch(e){
return Promise.reject(e);
}
}), 0);
};
const applyMiddleware = (middles, ctx) => compose(ctx)(...middles);
class SOS {
constructor() {
this.middleWares = [];
this.serve = http.createServer(async (req, res) => {
const ctx = { req, res };
//處理中間件
const handler = applyMiddleware(this.middleWares, ctx);
await handler(ctx);
res.end();
});
}
use(mid) {
this.middleWares.push(mid);
}
listen(...agr) {
this.serve.listen(...agr);
console.log('starting');
}
}
test.js
const sos = new SOS();
sos.listen(9009);
sos.use((next) =>async (ctx) => {
console.log('\npathname::',url.parse(ctx.req.url).pathname);
ctx.res.write(new Date()+'');
console.log('before 111');
ctx.res.write('before 111\n');
await next();
console.log('after 111');
ctx.res.write('after 111\n');
});
sos.use((next) =>async (ctx) => {
console.log('before 222');
ctx.res.write('before 222\n');
await next();
console.log('after 222');
ctx.res.write('end test222\n');
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('timeout 222 ');
ctx.res.write('timeout 222 \n');
return resolve();
}, 3000);
});
});
sos.use((next) =>async (ctx) => {
console.log('before 333');
ctx.res.write('before 333\n');
await next();
console.log('after 333');
ctx.res.write('end test333\n');
});