Table of Contents
1 簡單搭建http server
const http = require('http'); const url = require('url'); const port = 7799; const host = '127.0.0.1'; const srv = http.createServer(function (req, res) { let pathname = url.parse(req.url).pathname; if (pathname === '/index.html') { res.end('hello world'); } else { res.statusCode = 404; res.end('not found'); } }); srv.listen(port, host, function () { console.log(`server is running at http://${host}:${port}`); });
2 搭建的http server
const port = 7799; const host = '127.0.0.1'; const koa = require('koa'); const app = new koa(); app.listen(port, host, () => { console.log(`server running at http://${host}:${port}`); });
2.1 添加了簡單的返回內容
const port = 7799; const host = '127.0.0.1'; const koa = require('koa'); const app = new koa(); app.use(async (ctx, next) => { await next(); ctx.type = 'text/html'; // ctx.type = 'text/plain'; ctx.body = '<h1>hello, world</h1>' }); app.listen(port, host, () => { console.log(`server running at http://${host}:${port}`); });
2.2 拋出錯誤
const port = 7799; const host = '127.0.0.1'; const koa = require('koa'); const app = new koa(); app.use(async (ctx, next) => { await next(); // ctx.status = 404; ctx.type = 'text/html'; ctx.type = 'text/plain'; ctx.body = '<h1>hello, world</h1>'; ctx.throw(500); }); app.listen(port, host, () => { console.log(`server running at http://${host}:${port}`); });
2.3 中間件傳遞數據(state)
const port = 7799; const host = '127.0.0.1'; const koa = require('koa'); const app = new koa(); app.use(async (ctx, next) => { ctx.type = 'text/html'; ctx.body = '<h1>hello world</h1>'; ctx.state.name = '<h2>Oh yah</h2>' await next(); }); app.use(async (ctx, next) => { ctx.body = ctx.state.name + ctx.body; await next(); }); app.listen(port, host, () => { console.log(`server running at http://${host}:${port}`); });
2.4 中間件代碼執行過程
像穿過網同樣,逐層進入,在一層層返回(棧結構)css
2.4.1 執行代碼
const port = 7799; const host = '127.0.0.1'; const koa = require('koa'); const app = new koa(); app.use(async (ctx, next) => { console.log('1 before') await next(); console.log('1 finish') }); app.use(async (ctx, next) => { console.log('2 before') await next(); console.log('2 finish') }); app.use(async (ctx, next) => { console.log('3 before') await next(); console.log('3 finish') }); app.listen(port, host, () => { console.log(`server running at http://${host}:${port}`); });
2.4.2 訪問輸出的代碼
1 before 2 before 3 before 3 finish 2 finish 1 finish
2.4.3 多箇中間件合成一個
const port = 7799; const host = '127.0.0.1'; const koa = require('koa'); const app = new koa(); const compose = require('koa-compose'); app.use(async (ctx, next) => { console.log('org before') await next(); console.log('org finish') }); const all = compose([ async (ctx, next) => { console.log('1 before') await next(); console.log('1 finish') }, async (ctx, next) => { console.log('2 before') await next(); console.log('2 finish') }, async (ctx, next) => { console.log('3 before') await next(); console.log('3 finish') }]); app.use(all); app.listen(port, host, () => { console.log(`server running at http://${host}:${port}`); });
org before 1 before 2 before 3 before 3 finish 2 finish 1 finish org finish
2.4.4 測試響應耗時的列子
const port = 7799; const host = '127.0.0.1'; const koa = require('koa'); const app = new koa(); app.use(async (ctx, next) => { ctx.state.time = { beg: new Date().getTime(), end: '' }; await next(); ctx.state.time.end = new Date().getTime(); console.log('ms:', ctx.state.time.end - ctx.state.time.beg); }); app.use(() => { for(let i = 0; i < 1000000000; ++i){ ++i; } }); app.listen(port, host, () => { console.log(`server running at http://${host}:${port}`); });
3 一些中間件
3.1 koa-body
解析form-data數據html
const port = 7799; const host = '192.168.0.103'; const koa = require('koa'); const app = new koa(); const koaBody = require('koa-body'); app.use(koaBody({//還有不少配置參數 multipart : true //解決postman請求body一直爲空 })); app.use((ctx) => { ctx.type = 'html'; let method = ctx.method.toLowerCase(); if (method === 'get') { ctx.body = ` <h2>登陸</h2> <form method="post" action="/"> <div> <span>用戶名</span> <input name="user"/> </div> <div> <span>密碼</span> <input name="pwd"/> </div> <button type="submit">提交</button> </form> `; } else if (method === 'post') { let data = ctx.request.body; console.log(data) // console.log(ctx.req) } }); app.listen(port, host, () => { console.log(`server running at http://${host}:${port}`); });
3.2 koa-router
const port = 7799; const host = '192.168.0.103'; const koa = require('koa'); const app = new koa(); const Body = require('koa-body'); const Router = require('koa-router'); const router = new Router(); app .use(Body({//還有不少配置參數 multipart: true //解決postman請求body一直爲空 })) .use(router.routes()) .use(router.allowedMethods()); let page = ` <h2>登陸</h2> <form method="post" action="/"> <div> <span>用戶名</span> <input name="user"/> </div> <div> <span>密碼</span> <input name="pwd"/> </div> <button type="submit">提交</button> </form> `; router .get('/', (ctx) => { ctx.type = 'html'; ctx.body = page; }) .post('/', (ctx) => { console.log(ctx.request.body); ctx.type = 'html'; ctx.body = '<h1>提交成功</h1>' }); app.listen(port, host, () => { console.log(`server running at http://${host}:${port}`); });
3.3 koa-views 和 koa-static
用於請求靜態資源,中間件引入順序很重要,不然可能出現想不到的狀況(很操蛋)java
3.3.1 目錄結構
. ├── app.js ├── static └── views └── index.html
3.3.2 ./views/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>登陸</h2> <form method="post" action="/"> <div> <span>用戶名</span> <input placeholder="請輸入姓名" type="text" name="user" /> </div> <div> <span>密碼</span> <input placeholder="請輸入密碼" type="password" name="pwd"/> </div> <button type="submit">提交</button> </form> </body> </html>
3.3.3 ./app.js
const port = 7799; const host = '192.168.0.103'; const koa = require('koa'); const app = new koa(); const Body = require('koa-body'); const Router = require('koa-router'); const router = new Router(); const view = require('koa-views'); const statics = require('koa-static'); const path = require('path'); app .use(view(path.join(path.resolve(__dirname), 'views'), { map: {html: 'ejs'} })) .use(statics(path.join(path.resolve(__dirname), 'static'))); router .get('/', async (ctx) => { await ctx.render('index'); }) .post('/', (ctx) => { console.log(ctx.request.body); ctx.type = 'html'; ctx.body = '<h1>提交成功</h1>' }); // 放到上邊沒有正常顯示(緣由暫時不知道是啥) app .use(Body({//還有不少配置參數 multipart: true //解決postman請求body一直爲空 })) .use(router.routes()) .use(router.allowedMethods()); app.listen(port, host, () => { console.log(`server running at http://${host}:${port}`); });