koa middleware
app.use(async (ctx, next) => {await next();ctx.response.type = 'text/html';ctx.response.body = '<h1>Hello, koa2!</h1>';});
ctx是由koa传入的封装了 request 和 response 的变量,可以通过它访问request和responsenext是koa传入的将要处理的下一个 异步函数
为什么要调用 await next() ?
因为koa把很多 async 函数组成一个处理链,每个 async 函数都可以做一些自己的事情,然后 await next() 来调用下一个 async 函数。
每个async 函数成为 middleware,这些中间件可以组合起来。
app.use(async (ctx, next) => {console.log('执行顺序 --- 1')console.log(`${ctx.request.method} ${ctx.request.url}`); // 打印URLawait next(); // 调用下一个middlewareconsole.log('执行顺序 --- 6')});app.use(async (ctx, next) => {console.log('执行顺序 --- 2')const start = new Date().getTime(); // 当前时间await next(); // 调用下一个middlewareconsole.log('执行顺序 --- 5')const ms = new Date().getTime() - start; // 耗费时间console.log(`Time: ${ms}ms`); // 打印耗费时间});app.use(async (ctx, next) => {console.log('执行顺序 --- 3')await next();console.log('执行顺序 --- 4')ctx.response.type = 'text/html';ctx.response.body = '<h1>Hello, koa2!</h1>';});
// koa 的洋葱模型,先由外至内,然后,由内传外console.log('执行顺序 --- 1')...console.log('执行顺序 --- 3')...console.log('执行顺序 --- 6')
koa-router
为了处理URL,引入
koa-router这个middleware
koa-router 基本用例
npm install koa-router
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...');
这样使用时,如果 URL 越来越多, app.js 会变的很冗余。
koa-bodyparser
post请求时,通常会发送一个 表单 或者 JSON 作为 request 的 body ,但无论是Node.js 提供的原始request对象,还是 koa 提供的 request 对象,都没有解析 request 的body 的功能。
koa-bodyparser 中间件的作用就是: 解析原始request请求,然后,将解析后的参数邦定到
ctx.request.body中
npm install koa-bodyparser
...const bodyParser = require('koa-bodyparser');...// 然后再合适的位置加上app.use(bodyParser());...
由于middleware的顺序很重要,这个koa-bodyparser必须在router之前被注册到app对象上。
**
模块发封装 koa-router 处理 URL
url2-koa/|+- .vscode/| || +- launch.json <-- VSCode 配置文件|+- controllers/| || +- login.js <-- 处理login相关URL| || +- users.js <-- 处理用户管理相关URL|+- app.js <-- 使用koa的js|+- controller.js|+- package.json <-- 项目描述文件|+- node_modules/ <-- npm安装的所有依赖包
controllers / hello.js
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};
controller.js
const fs = require('fs');// add url-route in /controllers: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 if (url.startsWith('PUT ')) {var path = url.substring(4);router.put(path, mapping[url]);console.log(`register URL mapping: PUT ${path}`);} else if (url.startsWith('DELETE ')) {var path = url.substring(7);router.del(path, mapping[url]);console.log(`register URL mapping: DELETE ${path}`);} else {console.log(`invalid URL: ${url}`);}}}/* router 为 koa-router 对象* dir 为 处理URL文件所在的文件夹* 该方法主要作用是 先通过 fs.readdirSync 读取 处理URL的文件, 然后循环 引用该文件,* 然后,将引用的文件 传递给 addMapping 方法,并通过此方法将处理逻辑交给 koa-router 中间件处理*/function addControllers(router, dir) {fs.readdirSync(__dirname + '/' + dir).filter((f) => {return f.endsWith('.js');}).forEach((f) => {console.log(`process controller: ${f}...`);let mapping = require(__dirname + '/' + dir + '/' + f);addMapping(router, mapping);});}module.exports = function (dir) {letcontrollers_dir = dir || 'controllers',router = require('koa-router')(); // 调用 koa-routeraddControllers(router, controllers_dir);return router.routes();};
app.js
const Koa = require('koa');const bodyParser = require('koa-bodyparser');const controller = require('./controller');const app = new Koa();// 打印请求日志信息app.use(async (ctx, next) => {console.log(`Process ${ctx.request.method} ${ctx.request.url}...`);await next();});// parse request body:app.use(bodyParser()); // 在 router 调用前注册到 app上// add controllers:app.use(controller());app.listen(3000);console.log('app started at port 3000...');
**—-> 廖雪峰 github demo(模块化封装 处理 URL功能)
