理解koa中間件

在瞭解什麼是中間件以前,咱們先實現一個帶路由的koa應用。node

實現一個koa路由

要新建一個帶路由的koa應用特別容易,跟着個人步驟,幾分鐘就能完成。
首先,咱們打開命令行,新建一個koa-middleware目錄,進入這個目錄。npm

mkdir koa-middleware
cd koa-middleware/
複製代碼

而後,初始化package.json文件,執行init命令以後一路回車就ok。以後安裝咱們須要用到的koa和koa-router依賴。json

npm init
npm i koa koa-router --save
複製代碼

而後新建一個app.js文件,這個文件是應用的入口,在這裏編寫代碼瀏覽器

// app.js

const Koa = require('koa');
const router = require('koa-router')();
const app = new Koa();

router.get('/', async (ctx) => {

    ctx.body = "這是首頁";
})
router.get('/userCenter', async (ctx) => {

    ctx.body = '這是一個用戶頁面';
})

app.use(router.routes());
app.listen(3000);
複製代碼
node app
複製代碼

以後打開命令行,執行node app命令,打開瀏覽器訪問localhost:3000,就能夠看到咱們的頁面,改變url,就能夠切換頁面,這樣咱們的路由功能就實現了。bash

什麼是koa中間件

koa中間件指的是,匹配路由以前或者以後作的一系列操做。在上面這個例子裏,router.get這個函數有兩個參數,第一個參數就是匹配的路徑,第二個參數是一個函數。在這個函數裏,咱們返回了一個body是「這是首頁」的頁面。這就是咱們匹配路由以後作的操做,也就是中間件。在中間件裏咱們能夠作不少事情,好比:app

  • 執行任何代碼
  • 修改請求和響應對象
  • 利用next()函數調用下一個中間件

中間件也分幾種類型,他們分別是:koa

  • 應用級中間件
  • 路由級中間件
  • 錯誤處理中間件
  • 第三方中間件

應用級中間件

假設咱們如今有這麼一個需求,在全部的路由裏都打印出當前的時間。咱們能夠選擇每一個路由單獨寫一個方法來打印日期,但這是不可取的。這時咱們能夠用中間件來寫。async

const Koa = require('koa');
const router = require('koa-router')();
const app = new Koa();

// 用於在每次匹配路由前都打印一次當前時間的中間件
app.use(async (ctx,next)=>{
    console.log(new Date());
    await next();// 繼續向下匹配
})

router.get('/', async (ctx) => {

    ctx.body = "這是首頁";
})
router.get('/userCenter', async (ctx) => {

    ctx.body = '這是一個用戶頁面';
})

app.use(router.routes());
app.listen(3000);
複製代碼

這時,咱們每切換一次url,就能夠在控制檯打印一次當前時間(注意是控制檯打印,不是瀏覽器)。
這就是應用級中間件,寫法是app.use(),注意必須調用next()方法,纔會有後續的匹配路由,否則頁面就會返回404。函數

路由級中間件

應用級中間件是匹配全部的路由,即無論訪問哪一個路由以前,都會調用一次。那麼若是咱們只想在訪問某個路由以前作一些操做,該怎麼辦呢?這裏咱們用到的是路由級中間件,代碼以下:學習

const Koa = require('koa');
const router = require('koa-router')();
const app = new Koa();

router.get('/',async(ctx,next)=>{
    console.log('這是首頁');
    await next();
})

router.get('/', async (ctx) => {

    ctx.body = "這是首頁";
})

router.get('/userCenter', async (ctx) => {

    ctx.body = '這是一個用戶頁面';
})

app.use(router.routes());
app.listen(3000);
複製代碼

能夠看到,咱們訪問了兩次首頁路由,第一次作了一些操做以後,調用next(),第二次再訪問,再作另一些操做。這樣就能夠訪問具體某個路由前作一些操做了。

錯誤處理中間件

若是用戶在瀏覽器輸入了錯誤的url,瀏覽器會跳轉到404界面,但瀏覽器自帶的界面通常很醜,不夠美觀,因此咱們要本身設計符合咱們項目主題的404界面,這個時候就要用到錯誤處理中間件了。

const Koa = require('koa');
const router = require('koa-router')();
const app = new Koa();

app.use(async (ctx, next) => {
    next();
    if (ctx.status == 404) {
        ctx.status = 404; 
        ctx.body = "這是一個很是美觀的404頁面"
    }
});

router.get('/', async (ctx) => {

    ctx.body = "這是首頁";
})

router.get('/userCenter', async (ctx) => {

    ctx.body = '這是一個用戶頁面';
})

app.use(router.routes());
app.listen(3000);
複製代碼

第三方中間件

koa有不少第三方的中間件,好比koa-static,koa-bodyparser等,咱們使用這些第三方中間件的時候,要先下載下來,好比:

npm i koa-static koa-bodyparser --save
複製代碼

以後先引入再調用

const static = require('koa-static');
const staticPath = './static'; 
app.use(static(
    path.join( __dirname, staticPath) 
));

const bodyParser = require('koa-bodyparser'); 
app.use(bodyParser());
複製代碼

koa中間件的執行順序

在瞭解koa中間件執行順序以前,先來看這樣一段代碼:

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

app.use(async(ctx,next) =>{
    console.log(1);
    await next();
    console.log(2);
})

app.use(async(ctx,next) =>{
    console.log(3);
    await next();
    console.log(4);
})

app.use(async(ctx,next) =>{
    console.log(5);
    ctx.body = 'hello';
})

app.listen(3000);
複製代碼

本覺得執行結果會是1,2,3,4,5,沒想到竟然是1,3,5,4,2,這是怎麼回事呢? 這就是咱們要說到的koa中間件執行的洋蔥模型,以下圖:

咱們看到這張圖,能夠這麼理解:

  • 切開洋蔥,洋蔥的紋路是一圈一圈的,中間件以next()函數分界,next()以前的在洋蔥紋路的左邊,next()以後的在洋蔥紋路的右邊。
  • 整個程序的執行流程是從洋蔥左邊執行到洋蔥右邊,因此先執行完next()以前的,再執行next()以後的。
  • 執行順序靠前的中間件,在洋蔥模型裏的圈越大。執行順序越靠後的中間件,在洋蔥模型裏的圈越小。

洋蔥模型很是關鍵,它決定了咱們寫的程序的運行順序,好比咱們要寫錯誤處理中間件,就要把response的部分寫到next()函數以後,讓他在路由匹配完成以後再執行。

const Koa = require('koa');
const router = require('koa-router')();
const app = new Koa();

app.use(async (ctx, next) => {
    next();
    if (ctx.status == 404) {
        ctx.status = 404; 
        ctx.body = "這是一個很是美觀的404頁面"
    }
});

router.get('/', async (ctx) => {

    ctx.body = "這是首頁";
})

router.get('/userCenter', async (ctx) => {

    ctx.body = '這是一個用戶頁面';
})

app.use(router.routes());
app.listen(3000);
複製代碼

總結

本文從搭建一個帶路由的koa應用講起,以後引出了koa中間件的概念,再介紹了幾種經常使用的中間件,最後解釋了中間件的執行順序和洋蔥模型,很適合剛瞭解koa的朋友學習,若是對你有幫助,就分享出去吧。

相關文章
相關標籤/搜索