Koajs中間件之context(三)

Koajs中間件之定義(一)
Koajs中間件之next(二)
Koajs中間件之context(三)

第一篇文章中咱們講過,「在Koa中,中間件是指連貫整個 Koa 應用程序,並共享資源的獨立插件」,注意兩個詞,「連貫」與「共享資源」,與上面的代碼一一對應,「連貫」對應「next」,「共享資源對應context」。
Koa 中經過 context 處理上下文,下面分析一下 context。javascript

context 初始建立

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.state = {};
    return context;
}

不停的建立調用 context 對象,避免對context產生影響,初始 context 對象使用 Object.create() 來克隆對象
context 中包含了幾個個主要屬性,其中比較重要的有request、response、state。
Koa 中 分別提供 request.js 與 response.js 對原生 req 與 res 對象進行了處理,使得更易操做,例如在request.js 中將 req 原始請求參數由字符串類型替換爲對象類型,「?a=1&b=2」 <=> {a: 1, b: 2}。html

delegates

爲了簡化對於 context 的操做,Koa中 把 context 中須要調用的方法和屬性讀取,進行了委託。
有興趣的能夠研究研究 delegates 這個庫。java

delegate(proto, 'response')
  .method('attachment')
  .method('redirect')
  .method('remove')
  .method('vary')
  .method('set')
  .method('append')
  .method('flushHeaders')
  .access('status')
  .access('message')
  .access('body')
  .access('length')
  .access('type')
  .access('lastModified')
  .access('etag')
  .getter('headerSent')
  .getter('writable');

例如咱們經常使用的 「ctx.redirect(xxx)」 方法等同於 ctx.reponse.redirect(xxx);
例如輸出內容 ctx.body = 'xxx' 等同於 ctx.response.body = 'xxx';json

set & get 處理

對於context中的部分值的設置,進行了 set get 處理,例如 body 對象segmentfault

get body() {
    return this._body;
},
set body(val) {
    const original = this._body;
    this._body = val;

    if (this.res.headersSent) return;

    // no content
    if (val == null) {
        if (!statuses.empty[this.status]) this.status = 204;
        this.remove('Content-Type');
        this.remove('Content-Length');
        this.remove('Transfer-Encoding');
        return;
    }

    // set the status
    if (!this._explicitStatus) this.status = 200;

    // set the content-type only if not yet set
    const setType = !this.header['content-type'];

    // string
    if (typeof val == 'string') {
        if (setType) this.type = /^\s*</.test(val) ? 'html' : 'text';
        this.length = Buffer.byteLength(val);
        return;
    }

    // buffer
    if (Buffer.isBuffer(val)) {
        if (setType) this.type = 'bin';
        this.length = val.length;
        return;
    }

    // stream
    if (typeof val.pipe == 'function') {
        onFinish(this.res, destroy.bind(null, val));
        ensureErrorHandler(val, this.ctx.onerror);

        // overwriting
        if (original != null && original != val) this.remove('Content-Length');

        if (setType) this.type = 'bin';
        return;
    }

    // json
    this.remove('Content-Length');
    this.type = 'json';
}

當咱們經過 ctx.body 設置輸出內容的時候實際上在 Koa 內部進行了一系列處理,例如設置 body 未 null 的狀況下,會將 Http 返回狀態設置爲204。app

整體來講,Koa 中關於 context 的源碼初看比較複雜,其實是很是簡潔易明的。koa

參考資料

Mdn 類
Koa 官網this

相關文章
相關標籤/搜索