node.js之web開發 koa入門

用Node.js開發Web服務器端,有幾個顯著的優點:
速度快,很是快!這得益於Node.js天生是異步的。
常見的Web框架包括: Express Sails.js koa Meteor DerbyJS Total.js restify ……
構建工具備: Grunt Gulp Webpack ……
好消息是這個教程已經幫你選好了,你只須要跟着教程一條道走到黑就能夠了。

koa是Express的下一代基於Node.js的web框架,目前有1.x和2.0兩個版本。建議用2.0
Express是第一代最流行的web框架,它對Node.js的http進行了封裝
var express = require ( 'express' ); var app = express(); app.get( '/' , function (req, res) { res.send( 'Hello World!' ); }); app.listen( 3000 , function () { console.log( 'Example app listening on port 3000!' ); });
koa2的代碼看上去像這樣:
app. use (async (ctx, next) => { await next(); var data = await doReadFile(); ctx.response.type = 'text/plain' ; ctx.response.body = data; });

koa入門
如何安裝koa2
能夠用npm命令直接安裝koa。先打開命令提示符,務必把當前目錄切換到 文件所在的那個 目錄,而後執行命令:
npm install koa @2 . 0 . 0
任什麼時候候均可以直接刪除整個 node_modules 目錄,由於用 npm install 命令能夠完整地從新下載全部依賴。而且,這個目錄不該該被放入版本控制中。
或者經過下面方式安裝:
建立一個 package.json ,這個文件描述了咱們的 hello-koa 工程會用到哪些包
{ " 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" } }
其中, dependencies 描述了咱們的工程依賴的包以及版本號。其餘字段均用來描述項目信息, 可任意填寫。
而後,咱們在 hello-koa 目錄下執行 npm install 就能夠把所需包以及依賴包一次性所有裝好:
npm start 命令會讓npm執行定義在 package.json 文件中的start對應命令
// 導入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...' );
其中,參數 ctx 是由koa傳入的 封裝了request和response的變量 ,咱們能夠經過它訪問request和response, next 是koa傳入的將要處理的下一個異步函數。
async 標記的函數稱爲異步函數,在異步函數中,能夠用 await 調用另外一個異步函數,這兩個關鍵字將在ES7中引入。
每收到一個http請求,koa就會調用經過 app.use() 註冊的async函數,並傳入 ctx next 參數。
爲何要調用 await next()
緣由是koa把不少async函數組成一個處理鏈,每一個async函數均可以作一些本身的事情,而後用 await next() 來調用下一個async函數。咱們把每一個async函數稱爲middleware,這些middleware能夠組合起來,完成不少有用的功能。
console.log(`${ctx.request.method} ${ctx.request.url}`); // 打印URL
const ms = new Date().getTime() - start; // 耗費時間 console.log(`Time: ${ms}ms`); // 打印耗費時間
若是一個middleware沒有調用 await next() ,會怎麼辦?答案是後續的middleware將再也不執行了。
例如,一個檢測用戶權限的middleware能夠決定是否繼續處理請求,仍是直接返回403錯誤:
app.use(async (ctx, next ) => { if (await checkUserPermission(ctx)) { await next (); } else { ctx.response.status = 403 ; } });

處理url路由
"koa-router": "7.0.0"
const Koa = require( 'koa' ); // 注意require('koa-router')返回的是函數: const router = require( 'koa-router' )(); const app = new Koa(); // log request URL: app.use(async (ctx, next) => { console.log(`Process ${ctx.request.method} ${ctx.request.url}...`); await next(); }); // 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> '; }); // add router middleware: app.use(router.routes()); app.listen(3000); console.log('app started at port 3000...');
注意導入 koa-router 的語句最後的 () 是函數調用:

處理post請求
能夠用 router.post('/path', async ...
注意: 須要引入另外一個middleware來解析原始request請求,而後,把解析後的參數,綁定到 ctx.request.body 中。
"koa-bodyparser": "3.2.0"
const bodyParser = require ( 'koa-bodyparser' );
在合適的位置加上:
app. use (bodyParser());
因爲middleware的順序很重要,這個 koa-bodyparser 必須在 router 以前被註冊到 app 對象上。
name = ctx.request.body.name || '', // 默認值

把URL處理函數集中到某幾個js文件中
好比 在 controllers 目錄下編寫 index.js
var fn_index = async (ctx, next) => { ctx.response.body = ` <h1> Index </h1> <form action = "/signin" method = "post" > <p> Name: <input name = "name" value = "koa" ></p> <p> Password: <input name = "password" type = "password" ></p> <p><input type = "submit" value = "Submit" ></p> </form> `; };
...
module.exports = { 'GET /': fn_index, 'POST /signin': fn_signin };
另外一個
var fn_hello = async (ctx, next) => { var name = ctx.params.name; ctx.response.body = `<h1>Hello, ${name}! </h1> `; }; module.exports = { 'GET /hello/:name': fn_hello };
修改 app.js ,讓它自動掃描 controllers 目錄,找到全部 js 文件,導入,而後註冊每一個URL:
let 命令,用來聲明變量。它的用法相似於 var ,可是所聲明的變量,只在 let 命令所在的代碼塊內有效。 for 循環的計數器,就很合適使用 let 命令。
const fs = require ( 'fs' );
function addMapping (router, mapping) { for ( var url in mapping) { if (url.startsWith( 'GET ' )) { var path = url.substring( 4 ); router.get(path, mapping[url]); console.log(`register URL mapping: GET ${path}`); } else if (url.startsWith( 'POST ' )) { var path = url.substring( 5 ); router.post(path, mapping[url]); console.log(`register URL mapping: POST ${path}`); } else { console.log(`invalid URL: ${url}`); } } } function addControllers (router) { var files = fs.readdirSync(__dirname + '/controllers' ); var js_files = files.filter((f) => { return f.endsWith( '.js' ); }); for ( var f of js_files) { console.log(`process controller: ${f}...`); let mapping = require(__dirname + '/controllers/' + f); addMapping(router, mapping); } } //addControllers(router);
module.exports = function (dir) { let controllers_dir = dir || 'controllers' , // 若是不傳參數,掃描目錄默認爲'controllers' router = require ( 'koa-router' )(); addControllers(router, controllers_dir ); return router.routes(); };
主文件中
// 導入controller middleware: const controller = require ( './controller' ); ... // 使用middleware: app. use (controller());
其它:
Nunjucks 模板引擎
相關文章
相關標籤/搜索