let http = require('http'); let server = http.createServer((req, res) => { res.writeHead(200); res.end('hello world');}); server.listen(3000, () =>{ console.log('listenning on 3000'); });复制代码
const http=require('http'); const Koa=require('koa'); const app=new Koa(); app.listen(3000);复制代码
let url = require('url'); module.exports = {get query() { return url.parse(this.req.url, true).query; }};复制代码
module.exports = {get body() { return this._body; }, set body(data) { this._body = data; }, get status() { return this.res.statusCode; }, set status(statusCode) { if (typeof statusCode !== 'number') { throw new Error('something wrong!'); } this.res.statusCode = statusCode; }};复制代码
let proto = {}; function delegateSet(property, name) { proto.__defineSetter__(name, function (val) { this[property][name] = val; }); } function delegateGet(property, name) { proto.__defineGetter__(name, function () { return this[property][name]; }); } let requestSet = []; let requestGet = ['query']; let responseSet = ['body', 'status']; let responseGet = responseSet;requestSet.forEach(ele =>; { delegateSet('request', ele); }); requestGet.forEach(ele =>; { delegateGet('request', ele); }); responseSet.forEach(ele =>; { delegateSet('response', ele); }); responseGet.forEach(ele =>; { delegateGet('response', ele); }); module.exports = proto;复制代码
let http = require('http'); let context = require('./context'); let request = require('./request'); let response = require('./response'); createContext(req, res) { let ctx = Object.create(this.context); ctx.request = Object.create(this.request); ctx.response = Object.create(this.response); ctx.req = ctx.request.req = req; ctx.res = ctx.response.res = res; return ctx; }复制代码
let Koa = require('../src/application'); let app = new Koa(); app.use(async (ctx, next) => { console.log(1); await next(); console.log(6); }); app.use(async (ctx, next) => { console.log(2); await next();console.log(5); }); app.use(async (ctx, next) =>; { console.log(3); ctx.body = "hello world";console.log(4); }); app.listen(3000, () =>; { console.log('listenning on 3000'); });复制代码
根据上面的剥洋葱模型,以上代码的执行顺序应该是123456。 中间件模块的实现代码: compose() { return async ctx => { function createNext(middleware, oldNext) { return async () => { await middleware(ctx, oldNext); }} let len = this.middlewares.length; let next = async () => { return Promise.resolve(); }; for (let i = len - 1; i >= 0; i--) { let currentMiddleware = this.middlewares[i]; //将上一个中间件的next当做参数传给下一个中间件 next = createNext(currentMiddleware, next); } await next();};}callback() { return (req, res) => { let ctx = this.createContext(req, res); let respond = () => this.responseBody(ctx); let onerror = (err) =>; this.onerror(err, ctx); let fn = this.compose();return fn(ctx); };}复制代码
主要流程是通过use传进来的中间件是一个回调函数回调函数的参数是ctx上下文和next,next的作用是停止当前中间件,执行下一个中间件next()之前的代码,在下一个中间件运行的代码遇到next(),又会将执行权交给下下中间件。
中间件错误捕获: return fn(ctx).then(respond).catch(onerror); 框架层面异常捕获: let EventEmitter = require('events'); //koa构造函数继承events模块 class Application extends EventEmitter {} let app = new Koa(); //on监听函数 app.on('error', err => { console.log('error happends: ', err.stack); });复制代码