Koa 框架學習
Koa 框架學習
來自專欄 Node.js 學習
const Koa = require(koa);const app = new Koa();const port = 3000;app.use(ctx => { ctx.body = Hello Koa});app.listen(port);
以上為koa 創建一個server
現在我們分析源碼:
const app = new Koa()
做了那些事情:首先構造函數
constructor() { super(); this.proxy = false; this.middleware = []; this.subdomainOffset = 2; this.env = process.env.NODE_ENV || development; this.context = Object.create(context); this.request = Object.create(request); this.response = Object.create(response);}
聲明為中間件和context request response
該類Application繼承於Emitter
module.exports = class Application extends Emitter
listen 函數
listen(...args) { debug(listen); const server = http.createServer(this.callback()); return server.listen(...args); }
通過這張圖 我們可以發現app裡面掛載了context request 和response
中間件:
use(fn) { if (typeof fn !== function) throw new TypeError(middleware must be a function!); if (isGeneratorFunction(fn)) { deprecate(Support for generators will be removed in v3. + See the documentation for examples of how to convert old middleware + https://github.com/koajs/koa/blob/master/docs/migration.md); fn = convert(fn); } debug(use %s, fn._name || fn.name || -); this.middleware.push(fn); return this; }
用一個數組middleware 將當前的fn push進去
我們需要剖析一下:listen 裡面的this.callback();
callback() { const fn = compose(this.middleware); if (!this.listenerCount(error)) this.on(error, this.onerror); const handleRequest = (req, res) => { const ctx = this.createContext(req, res); return this.handleRequest(ctx, fn); }; return handleRequest; }
先將中間件組合為一個嵌套函數供返回的函數執行時候調用。
this.createContext 根據req 和res 封裝中間件所需要的ctx。
我們再看this.createContext如何定義:
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.state = {}; return context; }
我們看這個函數創建了簡單的對象,並且將他們的原型指定為我們app中對應的對象。
推薦閱讀: