1 專案搭建1.1 初始化目錄
安裝 mkdir koa-demo && cd koa-demo && npm init -y && npm i koa --save && code .
在 package.json 檔案中配置:
執行 npm start
開啟瀏覽器,輸入 http://localhost:3000/
當然大家現在可以使用瀏覽器檢視,因為是 get 請求,但是推薦大家安裝 postman,後期可以方便測試 post 請求或者上傳檔案功能。postman下載地址。
1.3 使用 postman 請求 http://localhost:3000/但是這裡每次改動程式碼都需要重新啟動服務,不是很方便,這裡我們安裝 nodemon 輔助工具,更改之後會自動重新整理,全域性或者當前專案下安裝都可以,我這裡全域性安裝下 npm i nodemon -g。
修改啟動命令為 "start": "nodemon index.js" (nodemon 會幫我們監聽 js, mjs, json 檔案的變化,自動啟動程式)
2 實現簡單 Koa大家都知道,Koa 是對 node 的封裝,先來個簡單的服務實現:
新建檔案 application.js使用 Koa 時是 new 的例項,所以需要實現個類,listen 方法監聽埠,use 方法實現掛載中介軟體,如下:
let http = require('http')class Application{ constructor() { this.callbackFunc } // 開啟http srever 傳入callback listen(...args) { let server = http.createServer(this.callback()) server.listen(...args) } /** * 掛載回撥函式 * @param {*} fn 回撥處理函式 */ use(fn) { this.callbackFunc = fn } /** * 獲取http server所需的callback函式 */ callback() { return (req, res) => { this.callbackFunc(req, res) } }}module.exports = Application
新建 example.js 檔案把剛建立的 application.js 檔案引入
let simpleKoa = require('./application')let app = new simpleKoa()app.use((req, res) => { res.writeHead(200) res.end('hello, uncertainty')})// 這次監聽 8000app.listen(8000, () => console.log('監聽8000埠'))
執行命令 nodemon example.js3 中介軟體
Koa 是一箇中間件框架,本身沒有捆綁任何中介軟體(核心程式碼簡潔)。本身支援的功能並不多,功能都可以透過中介軟體拓展實現。透過新增不同的中介軟體,實現不同的需求,從而構建一個 Koa 應用。Koa 的中介軟體就是函式,現在基本都是 async 函式。
app.use() 是用於註冊中介軟體並且必須是生成器函式(原始碼中有判斷,後面大版本會移除,2.0 為了向下相容)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;}
生成器函式:generator 是 ES6 新增的一個特殊函式,透過 function* 宣告,函式體內透過 yield 來指明函式的暫停點,該函式返回一個迭代器,並且函式執行到 yield 語句前面暫停,之後透過呼叫返回的迭代器 next() 方法來執行 yield 語句
我們也可以使用生成器函式做中介軟體(不推薦):
const Koa = require('koa')const app = new Koa()app.use(function *(next){ console.log(1) yield next; console.log(3) this.body = '你好,測不準啊'})app.use(function *(next){ console.log(2) yield next})app.listen(3000, () => { console.log('監聽3000埠')})
Koa 的中介軟體透過一種更加傳統的方式進行級聯,摒棄了以往 node 頻繁的回撥函式造成的複雜程式碼邏輯Koa 會把很多中間鍵函式組成一個處理鏈,每個中間鍵函式都可以做一些自己的事情,然後用 next() 來呼叫下一個中間鍵函式中間鍵必須是一個函式,可為非同步函式:透過es7中的async和await來處理use 內部封裝了兩個物件:ctx, nextctx 是 context 的一般叫成上下文,主要包括 request 和 response。body 是 http 協議中的響應體,header 是指響應頭,如果要拋異常可以直接使用 ctx.throw(500, '介面異常'),ctx.status 設定狀態碼,ctx.url 獲取請求 URL 等。next 起到串聯中介軟體的作用,透過呼叫 next 函式,把執行權交給下一個中介軟體。最後一箇中間件不使用該函式。4 編寫自己的中介軟體4.1 log 中介軟體日誌模組也是線上不可缺少的一部分,完善的日誌系統可以幫助我們迅速地排查出線上的問題。透過 Koa 中介軟體,我們可以實現屬於自己的日誌模組(當然可以直接用社群現成的庫):
新建 logger.jsconst fs = require('fs')module.exports = (options) => async (ctx, next) => { const startTime = Date.now() const requestTime = new Date() await next() const ms = Date.now() - startTime let logout = `${ctx.request.ip} -- ${requestTime} -- ${ctx.method} -- ${ctx.url} -- ${ms}ms` // 輸出日誌檔案 fs.appendFileSync('./log.txt', logout + '\n')}
入口檔案引入 logger.js 檔案
const Koa = require('Koa')const app = new Koa()const logger = require('./logger')app.use(logger())app.listen(3000, () => { console.log(`Server port is 3000.`)})
4.2 token 驗證前後端分離開發,我們常採用 JWT 來進行身份驗證,其中 token 一般放在 HTTP 請求中的 Header Authorization 欄位中(後面會介紹),每次請求後端都要進行校驗,不可能每個介面都寫判斷,Koa 透過編寫中介軟體來實現 token 驗證。