koa是Express的下一代基於Node.js的web框架,目前有1.x和2.0兩個版本。
koa 1.0 用es6的generator來實現異步
doreadFile()等有值時就返回。
var koa = require('koa');
var app = koa();
app.use('/test', function *() {
yield doReadFile1();
var data = yield doReadFile2();
this.body = data;
});
app.listen(3000);
爲了簡化異步代碼,es7引入了關鍵字async和await,可以輕鬆把一個function變爲一個異步模式。例如如下:
app.use(async (ctx, next) => {
await next();
var data = await doReadFile();
ctx.response.type = 'text/plain';
ctx.response.body = data;
});
創建koa項目 使用npm init創建node 項目,其中有package.json文件,是整個項目的配置文件,如下內容。
、
//post 請求中用來解析參數bodyparser
const bodyparser = require('koa-bodyparser');
//使用
app.use(bodyParser());
{
"name": "hello-koa2",
"version": "1.0.0",
"description": "Hello Koa 2 example with async",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"keywords": [
"koa",
"async"
],
"author": "Michael Liao",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/michaelliao/learn-javascript.git"
},
"dependencies": {
"koa": "2.0.0",
"koa-router": "7.0.0",
"koa-bodyparser": "3.2.0"
}
}
表示一些描述文件,scripts 表示入口文件 本文中是app.js文件。dependence表示引用的包。
導入koa
//導入koa 導入的是一個class 因此用大寫的Koa表示
const Koa = require('koa');
//創建一個Koa對象表示web app本身
const app = new Koa();
對於每一個http請求,koa將調用我們傳入的異步函數來處理。
app.use(async(ctx,next) =>{
console.log("process");
await next();
});
參數ctx表示上下文,封裝了request和response變量,,我們可以通過它訪問request和response,next
是koa傳入的將要處理的下一個異步函數。上面函數中 使用await next()表示處理下一個異步函數,只有等這個處理完了,才能執行下面的代碼。
app.listen表示監聽的端口。
await next()的作用。 koa把async函數組成一個處理鏈,買個async函數都可以做一些自己的函數,然後用await next()來調用下一個async函數,我們把每個async函數稱爲middleware 中間件,這些middleware可以組合起來,完成很多有用的功能。
我們可以寫如下函數來查看middleware的調用順序。
app.use(async(ctx,next)=>{
console.log("1"); //等這裏執行好 調用下一個異步函數
await next();
console.log(`${ctx.request.method} ${ctx.request.url}`); // 打印URL
});
app.use(async(ctx,next) => {
const start = new Date().getTime(); // 當前時間
console.log(2);
await next();
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>cdda<h1>';
})
依次打印出1 2 3所以可見順序是看app.use的加載順序。在await next()執行完畢後才執行下面的語句。
koa中的路由是一個非常重要的概念,在其中根據不同的路由執行不同的邏輯順序。
使用koa-router
// 注意require('koa-router')返回的是函數:
const router = require('koa-router')();
定義路由
// add url-route:
router.get('/hello/:name', async (ctx, next) => {
var name = ctx.params.name;
ctx.response.body = `<h1>Hello, ${name}!</h1>`;
});
router.get('/', async (ctx, next) => {
ctx.response.body = '<h1>Index</h1>';
});
隨後使用router
// add router middleware:
app.use(router.routes());
注意導入koa-router
的語句最後的()
是函數調用:
處理post請求。
post請求通常有表單,或者將參數放在body中,但無論是Node.js提供的原始request對象,還是koa提供的request對象,都不提供解析request的body的功能! 所以我們用koa-bodyparser來解析。
這裏要注意的是。koa-bodyparser必須在router之前被註冊到app對象中。
接下來,就可以處理簡單的post請求了。
var getuser = async (ctx, next) => {
var
name = ctx.request.body.name || '',
password = ctx.request.body.password || '';
console.log(name);
ctx.response.body = `<h1>Welcome, ${name}!</h1>`;
};
這樣就可以簡單的處理請求並返回。