Koa2的基本使用
[TOC]
简介
- koa2完全使用Promise并配合
async
来实现异步。但代码看起爱像是同步的。
入门程序
创建app.js
1234567891011121314151617// 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:const Koa = require('koa');// 创建一个Koa对象表示web app本身:const app = new Koa();// 对于任何请求,app将调用该异步函数处理请求://参数ctx是由koa传入的封装了request和response的变量,我们可以通过它访问request和response,next是koa传入的将要处理的下一个异步函数。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...');由
async
标记的函数称为异步函数,在异步函数中,可以用await
调用另一个异步函数。koa把很多async函数组成一个处理链,每个async函数都可以做一些自己的事情,然后用
await next()
来调用下一个async函数。我们把每个async函数称为middleware,这些middleware可以组合起来,完成很多有用的功能。app.use()
的顺序决定了middleware的顺序。1234567891011121314151617app.use(async (ctx, next) => {console.log(`${ctx.request.method} ${ctx.request.url}`); // 打印URLawait next(); // 调用下一个middleware});app.use(async (ctx, next) => {const start = new Date().getTime(); // 当前时间await next(); // 调用下一个middlewareconst 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>';});如果没有调用await next(); 那么后面的middleware都不会执行。(可以利用这个进行用户权限判定)
创建url映射
将不同的url映射到不同的函数,通过koa-router实现。
处理get请求
12345678910111213141516171819202122232425262728const 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();});// 注册一个get函数,并注明映射的urlrouter.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...');处理post请求
post请求通常会发送一个表单,或者JSON,它作为request的body发送,但无论是Node.js提供的原始request对象,还是koa提供的request对象,都不提供解析request的body的功能!
所以,我们又需要引入另一个middleware(koa-bodyparser)来解析原始request请求,然后,把解析后的参数,绑定到
ctx.request.body
中。在package.json中添加依赖
1"koa-bodyparser": "3.2.0"解析post请求
123456789101112131415161718192021//引入koa-bodyparserconst bodyParser = require('koa-bodyparser');//koa-bodyparser必须在router之前被注册到app对象上。app.use(bodyParser());router.post('/signin', async (ctx, next) => {//如果该字段不存在,默认值设置为''。varname = ctx.request.body.name || '',password = ctx.request.body.password || '';console.log(`signin with name: ${name}, password: ${password}`);if (name === 'koa' && password === '12345') {ctx.response.body = `<h1>Welcome, ${name}!</h1>`;} else {ctx.response.body = `<h1>Login failed!</h1><p><a href="/">Try again</a></p>`;}});app.use(router.routes());app.listen(3000);console.log('app started at port 3000...');
封装一个简单的url映射框架
我们将处理url映射的js按照功能划分,并统一放在controller包中。
新建controller包,在其内新建user.js
12345678910111213141516var fn_signin = async (ctx, next) => {varname = ctx.request.body.name || '',password = ctx.request.body.password || '';console.log(`signin with name: ${name}, password: ${password}`);if (name === 'koa' && password === '12345') {ctx.response.body = `<h1>Welcome, ${name}!</h1>`;} else {ctx.response.body = `<h1>Login failed!</h1><p><a href="/">Try again</a></p>`;}};//将signin方法暴露出去module.exports = {'POST /signin': fn_signin};新建controller.js负责扫描cintroller包下的js文件,并为其注册到router
1234567891011121314151617181920212223242526272829303132333435363738const 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,dir) {var files = fs.readdirSync(__dirname + dir+'');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);}}module.exports = function (dir) {letcontrollers_dir = dir || 'controllers', // 如果不传参数,扫描目录默认为'controllers'router = require('koa-router')();addControllers(router, controllers_dir);return router.routes();};新建app.js,调用controller.js提供的方法
1234567// 导入controller middleware:const controller = require('./controller');...// 使用middleware:app.use(controller());