iKcamp團隊製作|基於Koa2搭建Node.js實戰(含視頻)☞ 中間件用法

中間件用法——講解 Koa2 中間件的用法及如何開發中間件

���� iKcamp 製作團隊

原創作者:大哼阿幹三三小虎胖子小哈DDU可木晃晃
文案校對:李益大力萌AuDDU小溪裏小哈
風采主播:可木阿幹AuDDU小哈
視頻剪輯:小溪裏
主站運營:給力xixty
教程主編:張利濤


視頻地址:https://www.cctalk.com/v/15114357763623

文章

middleware 中間件

正是因爲中間件的擴展性才使得 Koa 的代碼簡單靈活。

app.js 中,有這樣一段代碼:

app.use(async (ctx, next)=>{
  await next()
  ctx.response.type = 'text/html'
  ctx.response.body = '<h1>Hello World</h1>'  
})

它的作用是:每收到一個 http 請求,Koa 都會調用通過 app.use() 註冊的 async 函數,同時爲該函數傳入 ctxnext 兩個參數。而這個 async 函數就是我們所說的中間件。

下面我們簡單介紹一下傳入中間件的兩個參數。

ctx

ctx 作爲上下文使用,包含了基本的 ctx.requestctx.response。另外,還對 Koa 內部對一些常用的屬性或者方法做了代理操作,使得我們可以直接通過 ctx 獲取。比如,ctx.request.url 可以寫成 ctx.url

除此之外,Koa 還約定了一箇中間件的存儲空間 ctx.state。通過 state 可以存儲一些數據,比如用戶數據,版本信息等。如果你使用 webpack 打包的話,可以使用中間件,將加載資源的方法作爲 ctx.state 的屬性傳入到 view 層,方便獲取資源路徑。

next

next 參數的作用是將處理的控制權轉交給下一個中間件,而 next() 後面的代碼,將會在下一個中間件及後面的中間件(如果有的話)執行結束後再執行。

注意: 中間件的順序很重要!

我們重寫 app.js 來解釋下中間件的流轉過程:

// 按照官方示例
const Koa = require('koa')
const app = new Koa()

// 記錄執行的時間
app.use(async (ctx, next) => {
  let stime = new Date().getTime()
  await next()
  let etime = new Date().getTime()
  ctx.response.type = 'text/html'
  ctx.response.body = '<h1>Hello World</h1>'
  console.log(`請求地址: ${ctx.path},響應時間:${etime - stime}ms`)
});

app.use(async (ctx, next) => {
  console.log('中間件1 doSoming')
  await next();
  console.log('中間件1 end')
})

app.use(async (ctx, next) => {
  console.log('中間件2 doSoming')
  await next();
  console.log('中間件2 end')
})

app.use(async (ctx, next) => {
  console.log('中間件3 doSoming')
  await next();
  console.log('中間件3 end')
})

app.listen(3000, () => {
  console.log('server is running at http://localhost:3000')
})

運行起來後,控制檯顯示:

server is running at http://localhost:3000

然後打開瀏覽器,訪問 http://localhost:3000,控制檯顯示內容更新爲:

server is running at http://localhost:3000
中間件1 doSoming
中間件2 doSoming
中間件3 doSoming
中間件3 end
中間件2 end
中間件1 end
請求地址: /,響應時間:2ms

從結果上可以看到,流程是一層層的打開,然後一層層的閉合,像是剝洋蔥一樣 —— 洋蔥模型。

此外,如果一箇中間件沒有調用 await next(),會怎樣呢?答案是『後面的中間件將不會執行』。

修改 app.js 如下,我們去掉了第三個中間件裏面的 await

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

// 記錄執行的時間
app.use(async (ctx, next)=>{
  let stime = new Date().getTime()
  await next()
  let etime = new Date().getTime()
  ctx.response.type = 'text/html'
  ctx.response.body = '<h1>Hello World</h1>'
  console.log(`請求地址: ${ctx.path},響應時間:${etime - stime}ms`)
});

app.use(async (ctx, next) => {
  console.log('中間件1 doSoming')
  await next();
  console.log('中間件1 end')
})

app.use(async (ctx, next) => {
  console.log('中間件2 doSoming')
  // 注意,這裏我們刪掉了 next
  // await next()
  console.log('中間件2 end')
})

app.use(async (ctx, next) => {
  console.log('中間件3 doSoming')
  await next();
  console.log('中間件3 end')
})

app.listen(3000, () => {
  console.log('server is running at http://localhost:3000')
})

重新運行代碼後,控制檯顯示如下:

server is running at http://localhost:3000
中間件1 doSoming
中間件2 doSoming
中間件2 end
中間件1 end
請求地址: /,響應時間:1ms

與我們的預期結果『後面的中間件將不會執行』是一致的。

下一篇:我們將學習下如何響應瀏覽器的各種請求。

上一篇:iKcamp新課程推出啦~~~~~iKcamp團隊製作|基於Koa2搭建Node.js實戰(含視頻)☞ 環境準備

推薦: 翻譯項目Master的自述:

乾貨|人人都是翻譯項目的Master

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章