首先初始化項目html
npm init -y 項目名稱node
安裝koaweb
$ npm i koa
咱們建立一個目錄hello-koa
並做爲工程目錄用VS Code打開。而後,咱們建立app.js
,輸入如下代碼:sql
// 導入koa,和koa 1.x不一樣,在koa2中,咱們導入的是一個class,所以用大寫的Koa表示: const Koa = require('koa'); // 建立一個Koa對象表示web app自己: const app = new Koa(); // 對於任何請求,app將調用該異步函數處理請求: app.use(async (ctx, next) => { await next(); ctx.response.type = 'text/html'; ctx.response.body = '<h1>Hello, koa2!</h1>'; }); // 在端口3000監聽: app.listen(3000); console.log('app started at port 3000...');
對於每個http請求,koa將調用咱們傳入的異步函數來處理:npm
async (ctx, next) => { await next(); // 設置response的Content-Type: ctx.response.type = 'text/html'; // 設置response的內容: ctx.response.body = '<h1>Hello, koa2!</h1>'; }
其中,參數ctx
是由koa傳入的封裝了request和response的變量,咱們能夠經過它訪問request和response,next
是koa傳入的將要處理的下一個異步函數。json
上面的異步函數中,咱們首先用await next();
處理下一個異步函數,而後,設置response的Content-Type和內容。數組
由async
標記的函數稱爲異步函數,在異步函數中,能夠用await
調用另外一個異步函數,這兩個關鍵字將在ES7中引入。瀏覽器
打開瀏覽器,輸入http://localhost:3000
,便可看到效果:ruby
還能夠直接用命令node app.js
在命令行啓動程序,或者用npm start
啓動。npm start
命令會讓npm執行定義在package.json
文件中的start對應命令:bash
"scripts": {
"start": "node app.js" }
讓咱們再仔細看看koa的執行邏輯。核心代碼是:
app.use(async (ctx, next) => {
await next();
ctx.response.type = 'text/html';
ctx.response.body = '<h1>Hello, koa2!</h1>'; });
每收到一個http請求,koa就會調用經過app.use()
註冊的async函數,並傳入ctx
和next
參數。
咱們能夠對ctx
操做,並設置返回內容。可是爲何要調用await next()
?
緣由是koa把不少async函數組成一個處理鏈,每一個async函數均可以作一些本身的事情,而後用await next()
來調用下一個async函數。咱們把每一個async函數稱爲middleware,這些middleware能夠組合起來,完成不少有用的功能。
例如,能夠用如下3個middleware組成處理鏈,依次打印日誌,記錄處理時間,輸出HTML:
app.use(async (ctx, next) => { console.log(`${ctx.request.method} ${ctx.request.url}`); // 打印URL await next(); // 調用下一個middleware
console.log('請求處理完畢');
}); app.use(async (ctx, next) => { const start = new Date().getTime(); // 當前時間 await next(); // 調用下一個middleware const ms = new Date().getTime() - start; // 耗費時間 console.log(`Time: ${ms}ms`); // 打印耗費時間 }); app.use(async (ctx, next) => { await next(); ctx.response.type = 'text/html'; ctx.response.body = '<h1>Hello, koa2!</h1>'; });
請求結果:
middleware的順序很重要,也就是調用app.use()
的順序決定了middleware的順序。
此外,若是一個middleware沒有調用await next()
,會怎麼辦?答案是後續的middleware將再也不執行了。這種狀況也很常見,例如,一個檢測用戶權限的middleware能夠決定是否繼續處理請求,仍是直接返回403錯誤:
app.use(async (ctx, next) => { if (await checkUserPermission(ctx)) { await next(); } else { ctx.response.status = 403; } });
理解了middleware,咱們就已經會用koa了!
最後注意ctx
對象有一些簡寫的方法,例如ctx.url
至關於ctx.request.url
,ctx.type
至關於ctx.response.type
。
更多別名
如下訪問器和 Request 別名等效:
ctx.header
ctx.headers
ctx.method
ctx.method=
ctx.url
ctx.url=
ctx.originalUrl
ctx.origin
ctx.href
ctx.path
ctx.path=
ctx.query
ctx.query=
ctx.querystring
ctx.querystring=
ctx.host
ctx.hostname
ctx.fresh
ctx.stale
ctx.socket
ctx.protocol
ctx.secure
ctx.ip
ctx.ips
ctx.subdomains
ctx.is()
ctx.accepts()
ctx.acceptsEncodings()
ctx.acceptsCharsets()
ctx.acceptsLanguages()
ctx.get()
如下訪問器和 Response 別名等效:
ctx.body
ctx.body=
ctx.status
ctx.status=
ctx.message
ctx.message=
ctx.length=
ctx.length
ctx.type=
ctx.type
ctx.headerSent
ctx.redirect()
ctx.attachment()
ctx.set()
ctx.append()
ctx.remove()
ctx.lastModified=
ctx.etag=