功能演进:
V1:
V1.x:
- JS切换为TS
- request/response装饰增强
- 细化统一异常处理
- 细化流程控制
V2:
- AOP自定义注解拦截
- IOC管理注入@Controller/@Service组件
- @Request标记handler
- @ResponseBody自动处理返回值
- 事务
V2.x:
V1:
SOS.js
const http = require('http');
const url = require('url');
const EventEmitter = require('events');
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();
}
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);
}
}), 1);
};
const applyMiddleware = (middles, ctx) => compose(ctx)(...middles);
class SOS extends EventEmitter {
constructor() {
this.middleWares = [];
this.serve = http.createServer(async (req, res) => {
const ctx = { req, res };
const handler = applyMiddleware(this.middleWares, ctx);
await handler(ctx);
res.finisn || res.end();
});
}
use(mid) {
this.middleWares.push(mid);
}
listen(...agr) {
this.serve.listen(...agr);
console.log('starting');
}
onerror(err, ctx) {
if (err.code === 'ENOENT') {
ctx.status = 404;
}
else {
ctx.status = 500;
}
let msg = err.message || '000 error';
ctx.res.end(msg);
this.emit('error', err);
}
}
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');
});