博客 / 詳情

返回

Node學習——Kao框架

1.簡介

koa框架是一個遵循洋葱模型的輕量級的nodejs框架,將大部分工作都拋給中間件來處理,框架只專注於compose各個中間件,並按照use註冊的順序逐個執行中間件。

2.安裝使用

安裝:npm install koa -s
使用:

const Koa = require('koa');
const app = new Koa;
app.listen(3000);

3.中間件的使用

const Koa  = require('koa');
const mount = require('koa-mount');

const app = new Koa();
app.use(mount('/api', function() {
      .....
}));
app.listen(80);

以上代碼使用了koa-mount來進行進行路由處理,使用koa實例上的use方法將mount函數返回的函數註冊為中間件。以下是koa中use函數。

  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;
  }

可以看到,一個函數中間件在use函數中先是判斷是否為generator函數,如果是,使用koa-convert轉換,最終都會放入koa實例的middleware數組中保存,供後續調用。
a.説一下isGeneratorFunction函數,這個函數的思路是通過Function動態創建一個generate函數,然後取其原型與傳入的函數的原型對比,如果相同説明傳入函數就是generate函數。
b.再説一下convert函數,這個函數在koa-convert包中,就是內部又引入了co庫,將傳入的generate函數包裹,達到自執行的效果。

回過頭説一下koa的listen函數,代碼如下:

  listen(...args) {
    debug('listen');
    const server = http.createServer(this.callback());
    return server.listen(...args);
  }

  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;
  }

可以看到,listen函數內部調用了node核心模塊http,創建了一個http服務,並將自身的callback函數作為http服務的響應函數。
而callback函數內部則是通過compose將之前註冊的中間件包裹,然後通過createContext將req和res封裝到一個ctx中,逐層傳入後面的中間件中。ctx內容如下:

4.request和response處理

如上所示,req和res被封裝到了context中,在各個中間件都可以從參數中得到,中間件可以拿到兩個參數:一個是context,各中間件可以通過它來進行通信和同步狀態;第二個是next,調用它會執行後續中間件。使用示例如下:

const Koa = require('koa')
const app = new Koa()
//聲明一個main中間件,如果你急於瞭解中間件可以跳轉到(三)
const main = (ctx,next) =>{
if (ctx.request.accepts('json')) {
    ctx.response.type = 'json';
    ctx.response.body = { data: 'Hello World' };
  } else if (ctx.request.accepts('html')) {
    ctx.response.type = 'html';
    ctx.response.body = '<p>Hello World</p>';
  } else if (ctx.request.accepts('xml')) {
    ctx.response.type = 'xml';
    ctx.response.body = '<data>Hello World</data>';
  } else{
    ctx.response.type = 'text';
    ctx.response.body = 'Hello World';
  };
}; //直接運行頁面中會顯示json格式,因為我們沒有設置請求頭,所以每一種格式都是ok的。   

app.use(main)//app.use()用來加載中間件。
app.listen(3000)

可以看到,我們給返回數據賦值可以直接使用’=‘賦值,在koa的response中body通過set屬性,將設置進來的body值按照其type進行處理,如下。

  set body(val) {
    const original = this._body;
    this._body = val;

    // no content
    if (null == val) {
      if (!statuses.empty[this.status]) this.status = 204;
      if (val === null) this._explicitNullBody = true;
      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.has('Content-Type');

    // string
    if ('string' === typeof val) {
      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 (val instanceof Stream) {
      onFinish(this.res, destroy.bind(null, val));
      if (original != val) {
        val.once('error', err => this.ctx.onerror(err));
        // overwriting
        if (null != original) this.remove('Content-Length');
      }

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

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

5.靜態資源

使用koa-static中間件來處理靜態資源,實例如下:
安裝npm: npm install koa-static
使用:

const Koa = require('koa');
const app = new Koa();
const path = require('path');
const serve = require('koa-static');

const main = serve(path.join(__dirname));

app.use(main);
app.listen(3000);

6.post請求的body處理

可以使用koa-body中間件來處理,
安裝:npm install koa-body -s
使用:

const Koa = require('koa');
const {koaBody} = require('koa-body');

const app = new Koa();
app.use(koaBody({
    multipart: true
});
app.use(function(ctx, next) {
    console.log(ctx.request.body);
});
app.listen(3000);

如上,koa-body會將post請求的body解析後保存在ctx中,供後續中間件使用。

更對參數參考:https://blog.csdn.net/nullccc/article/details/113839289

參考資料:

https://zhuanlan.zhihu.com/p/67239164?utm_id=0
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.