Closed TokenYangForever closed 6 years ago
context、request、response
constructor() { ....... this.context = Object.create(context); this.request = Object.create(request); this.response = Object.create(response); }
http.createServer
callback
const server = http.createServer(this.callback()); return server.listen(...args);
koa-convert
middleware
this
use(fn) { if (typeof fn !== 'function') throw new TypeError('middleware must be a function!'); if (isGeneratorFunction(fn)) { fn = convert(fn); } this.middleware.push(fn); return this; }
然后用createContext函数生成一个context上下文对象。
createContext
context
const fn = require('koa-compose')(this.middleware); if (!this.listeners('error').length) this.on('error', this.onerror); const handleRequest = (req, res) => { const ctx = this.createContext(req, res); return this.handleRequest(ctx, fn); }; return handleRequest;
Object.create
createContext(req, res) { const context = Object.create(this.context); const request = context.request = Object.create(this.request); const response = context.response = Object.create(this.response); context.app = request.app = response.app = this; context.req = request.req = response.req = req; context.res = request.res = response.res = res; request.ctx = response.ctx = context; request.response = response; response.request = request; context.originalUrl = request.originalUrl = req.url; context.cookies = new Cookies(req, res, { keys: this.keys, secure: request.secure }); request.ip = request.ips[0] || req.socket.remoteAddress || ''; context.accept = request.accept = accepts(req); context.state = {}; return context; }
fnMiddleware(ctx)
respond(ctx)
handleRequest(ctx, fnMiddleware) { const res = ctx.res; res.statusCode = 404; const onerror = err => ctx.onerror(err); const handleResponse = () => respond(ctx); onFinished(res, onerror); return fnMiddleware(ctx).then(handleResponse).catch(onerror); }
这个函数就是通过已经处理好了的ctx对象,再做一些处理,最后调用ctx.res.end()方法返回最终的response报文。
function respond(ctx) { // allow bypassing koa if (false === ctx.respond) return; const res = ctx.res; if (!ctx.writable) return; let body = ctx.body; const code = ctx.status; // ignore body if (statuses.empty[code]) { // strip headers ctx.body = null; return res.end(); } if ('HEAD' == ctx.method) { if (!res.headersSent && isJSON(body)) { ctx.length = Buffer.byteLength(JSON.stringify(body)); } return res.end(); } // status body if (null == body) { body = ctx.message || String(code); if (!res.headersSent) { ctx.type = 'text'; ctx.length = Buffer.byteLength(body); } return res.end(body); } // responses if (Buffer.isBuffer(body)) return res.end(body); if ('string' == typeof body) return res.end(body); if (body instanceof Stream) return body.pipe(res); // body: json body = JSON.stringify(body); if (!res.headersSent) { ctx.length = Buffer.byteLength(body); } res.end(body); }
constructor
application
listen
koa-compose
fnMiddleware
ctx
前言
application.js
constructor
context、request、response
,原型分别来自其他三个js文件,用Object.create继承原型。这三个文件后面会再介绍。listen
http.createServer
方法新建一个http服务器,并监听传入的端口号。回调函数调用callback
,这个函数里会依次执行中间件函数,后面会介绍。use
koa-convert
模块,把他转换为普通函数。middleware
表示使用了的中间件,use方法把中间件函数push到middleware中。最后返回实例对象this
,以便可以链式调用callback
middleware
中间件数组,进行处理变成一个相当于generator函数。然后用
createContext
函数生成一个context
上下文对象。createContext
context
对象,上下文对象应该是koa框架的核心内容。下面介绍下context对象的一些属性Object.create
新建的对象Object.create
新建的对象http.createServer
方法产生的原生req对象http.createServer
方法产生的原生res对象handleRequest
fnMiddleware(ctx)
,把context作为参数传入,处理完成后再用respond(ctx)
处理返回response。response
这个函数就是通过已经处理好了的ctx对象,再做一些处理,最后调用ctx.res.end()方法返回最终的response报文。
小结
constructor
构造函数生成application
实例(app) ==>>middleware
数组中 ==>>listen
函数,新建http服务器,监听端口==>>context
上下文对象,使用koa-compose
处理中间件函数,生成fnMiddleware
函数 ==>>fnMiddleware
函数处理ctx
上下文对象,也就是依次调用中间件函数处理ctx ==>>