koa,瞭解一下?

花樣前端發表於2018-07-01

1、koa介紹

koa是一個相對於express來說,更小,更健壯,更富表現力的Web框架。koa通過組合不同的generator來避免繁瑣的回撥函式呼叫。koa的核心庫沒有繫結任何的中介軟體,僅僅提供了一個輕量優雅的函式庫,使得編寫Web應用變得得心應手。

1-1、使用koa

在專案目錄路徑下執行命令

npm install --save-dev koa
複製程式碼

就可以在本地安裝koa模組。 安裝完成後,寫一個hello world來驗證是否生效。 hello world程式碼十分簡單。

const koa = require('koa');
const app = koa();

app.use(function *(ctx) {
  ctx.body = 'hello world';
});

app.listen(3000)
複製程式碼

上面程式碼就實現了koa的helloworld。

第4行呼叫的app.use()傳入了一個generator方法,就是koa中介軟體的基本實現。

koa應用的實現就是由一個一個的中介軟體來實現。每一箇中介軟體都是一個generator方法,通過yield語句,將一個一箇中介軟體邏輯級聯起來

2、koa原始碼

koa.js的原始碼有4個檔案,分別是

  • lib/application.js
  • lib/context.js
  • lib/request.js
  • lib/response.js。

從名字中可以看出來,context.js,request.js,response.js分別是上下文環境物件,request物件,response物件,而application.js就是koa.js的核心程式碼。

在上面的例子中,都使用了兩個介面,use和listen。下面我們先介紹下這兩個方法, 下面是application.js中這兩個方法的原始碼:

// ...
app.listen = function(){
  debug('listen');
  var server = http.createServer(this.callback());
  return server.listen.apply(server, arguments);
};
// ...
app.use = function(fn){
  if (!this.experimental) {
    // es7 async functions are not allowed,
    // so we have to make sure that `fn` is a generator function
    assert(fn && 'GeneratorFunction' == fn.constructor.name, 'app.use() requires a generator function');
  }
  debug('use %s', fn._name || fn.name || '-');
  this.middleware.push(fn);
  return this;
};
// ...
複製程式碼

可以看出來,use的作用就是將傳入的中介軟體generator方法放到this.middleware中。listen介面的作用其實就是啟動了一個server,並將請求處理設定為 this.callback()的返回方法。 然後我們來看下this.callback怎麼寫的:

// ...
app.callback = function(){
  if (this.experimental) {
    console.error('Experimental ES7 Async Function support is deprecated. Please look into Koa v2 as the middleware signature has changed.')
  }
  var fn = this.experimental
    ? compose_es7(this.middleware)
    : co.wrap(compose(this.middleware));
  var self = this;

  if (!this.listeners('error').length) this.on('error', this.onerror);

  return function(req, res){
    res.statusCode = 404;
    var ctx = self.createContext(req, res);
    onFinished(res, ctx.onerror);
    fn.call(ctx).then(function () {
      respond.call(ctx);
    }).catch(ctx.onerror);
  }
};
// ...
複製程式碼

其中的核心程式碼是這兩句:

// ...
co.wrap(compose(this.middleware));
// ...
return function(req, res){
  // ...
  fn.call(ctx).then(function () {
    respond.call(ctx);
  }).catch(ctx.onerror);
}
// ...
複製程式碼

其中compose(this.middleware)的作用是將傳入的中介軟體陣列合併成層層呼叫的generator函式。co.wrap()方法的作用是將generator數轉化成一個自執行的函式。最後的fn.call(ctx)就開始逐步執行中介軟體了。

3、koa常用中介軟體

koa框架本身的功能十分簡單,koa應用的功能都是通過中介軟體來實現的,下面我們來介紹常用的幾個koa中介軟體。

3-1、 koa-static

koa-static是管理靜態檔案請求的中介軟體。比如要請求html,JS,圖片的靜態檔案時,就可以使用koa-static來實現。 舉個例子,比如專案根目錄下得static目錄用於存放靜態檔案,那麼如下程式碼就可以實現該目錄的靜態檔案請求

const path = require('path');
const staticServer = require('koa-static');

app.use(staticServer(path.join(__dirname, 'static')));
複製程式碼

3-2、koa-router

koa-router是一個路由中介軟體,用法如下:

const router = require('koa-router')();

// 監聽url請求
router.get('/list', function *() {
  // ...
});
router.post('/user/register', function *() {
  // ...
});
複製程式碼

3-3、koa-session

session管理的中介軟體,用法:

const session = require('koa-session');

app.use(session(app));

router.post('./user/login', function *() {
  this.session.user = user;
});
複製程式碼

相關文章