在?用Node.js實現一個http服務器框架?

功能演進:

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');
});

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章