Koa2源码阅读: ctx

2018-06-17  本文已影响0人  ceido

前言

koa 框架的目录结构如图:


image.png

koa/lib 文件夹下, 只有 4 个文件, 分别是 application.js, context.js, request.js, response.js.

application.js 是 koa 的入口文件, context.js 的作用是创建网络请求的上下文对象, request.js 是用于包装 koa 的 request 对象的, response.js则是用于包装 koa 的 response 对象的。

正文

下面就通过自己写一个小koa来理解它,我叫它为coa。

(1)先写个原生服务的:

server.js:

const http = require('http')

const server = http.createServer((req, res) => {
    res.writeHead(200)                              
    res.end('hello coa2')
})

server.listen(8000, () => {
    console.log('server start')
})

(2)然后我们新建一个文件application.js,进行简单的封装:

const http = require('http')
class Application {
    constructor() {
        this.callback = () => {}
    }

    use(callback) {
        this.callback = callback
    }
    listen(...args) {
        const server = http.createServer((req, res) => {
            this.callback(req, res)
        })
        server.listen(...args)
    }
}

module.exports = Application

这时候我们在server.js中就这样用了:

const Coa = require('./coa2')
const app = new Coa()

app.use((req, res) => {
    res.writeHead(200)
    res.end('hello coa2')
})

app.listen(8000, () => {
    console.log('coa!')
})

(3)将req、res挂载到ctx


const http = require('http')

let request = {
    get url() {
        return this.req.url
    }
}

let resopnse = {
    get body() {
        return this._body
    },

    set body(val) {
        this._body = val
    }
}

let context = {
    get url() {
        return this.request.url
    },
    get body() {
        return this.resopnse.body
    },

    set body(val) {
        this.resopnse.body = val
    }
}

class Application {
    constructor() {
        this.context = context
        this.request = request
        this.resopnse = resopnse
    }

    use(callback) {
        this.callback = callback
    }
    listen(...args) {
        const server = http.createServer(async (req, res) => {
            let ctx = this.createCtx(req, res)
            await this.callback(ctx)
            ctx.res.end(ctx.body)
        })
        server.listen(...args)
    }
    createCtx(req, res) {
        let ctx = Object.create(this.context)
        ctx.request = Object.create(this.request)
        ctx.resopnse = Object.create(this.resopnse)
        ctx.req = ctx.request.req = req
        ctx.res = ctx.resopnse.res = res
        return ctx
    }
}

module.exports = Application

我们先创建request、resopnse、context。使用get、set是因为...因为源码是这么写的。哈,其实就是访问和设置时要做些额外的操作。

然后我们把request、resopnse、context挂到Application实例中,再通过调用createCtx把原生的req,res传入,整合一下后返回ctx。这样整合是为了以后便于扩展。

然后我们在server.js中的就可以这样写了:

const Coa = require('./coa2')
const app = new Coa()

app.use(async ctx => {
    ctx.body = 'hello coa2 ' + ctx.url
})


app.listen(8000, () => {
    console.log('coa!')
})

现在开始就有点像koa了有没有!

上一篇 下一篇

猜你喜欢

热点阅读