Express
和 Koa
基本上是我们最熟悉的开发框架。
我们在这里选用 Koa2
,不仅仅是因为它是由 Express
原班人马打造的下一代Web开发框架, 更是因为它遵循的“洋葱模型”。且在 koa2
中使用 Promise
, 因此可以结合 async/await
编写出更易于理解与维护的代码,更符合 Node.js
的开发习惯。
那么,到底什么是“洋葱模型”呢?我们从AOP
讲起。
AOP(Aspect Oriented Programming)通过预编译方式和运行期间动态代理实现程序功能的 统一维护 的一种技术。
简单来说,AOP利用一种称为"横切"的技术,将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制等,封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
特点:低耦合,高聚合。
如果我们想要穿透一个洋葱,就需要先穿过一层一层的洋葱皮,到达洋葱核心,再从核心穿过洋葱皮到达另一边。
洋葱的每一层皮,对应的就是一个中间件,其生命周期大致有:
多个中间件组合就形成了一个洋葱,由 request
到 response
就形成了一次穿透,这就形成了洋葱模型
。
宏观上来说,Koa
本身只是一个遵循洋葱模型
的中间件管理器,不与任何的中间件绑定。再利用 koa-static
koa-bodyparser
koa-router
等插件以中间件形式加载。形成最基本的http框架。
对于Web应用而言,一次Http请求通常包含很多工作,如Cookie处理、ip过滤、权限验证、异常处理、记录日志等,这些基础方法都可以以中间件形式加载在Koa框架上。隔离与业务逻辑之间的细节,提升开发效率。
这也是 AOP
面向切面编程的一种应用。
npm install koa koa-body koa-logger koa-router --save
修改 src/app.js
项目入口文件
import Koa2 from 'koa' import koaLogger from 'koa-logger' import koaBody from 'koa-body' import router from './router' const env = process.env.NODE_ENV || 'development' const app = new Koa2() // Console app.use(koaLogger()) // Body Format app.use(koaBody()) // Routes app.use(router.routes()) app.use(router.allowedMethods()) if (env === 'development') { app.use(async (ctx, next) => { const start = new Date() await next() const ms = new Date() - start console.log(`${ctx.method} ${ctx.url} - ${ms}ms`) }) } app.listen(9000) console.log('Now start API server on port 9000 ...')
创建 src/router.js
路由文件
import KoaRouter from 'koa-router' const router = new KoaRouter() router.get('/', (ctx, next) => { ctx.body = 'hello focus' }) router.get('/error', (ctx, next) => { throw new Error('Ops...') }) export default router
npm run dev
现在我们就可以在浏览器访问 http://localhost:9000/
但是,如果我们访问 http://localhost:9000/error 会发现显示的是服务错误信息,并且返回的状态码为500
作为一个API服务器,我们希望即使程序出错了,返回的状态码依然是200,错误信息放在响应数据里,且依然为JSON格式。
在 src/app.js
入口中添加一个中间件
// code ... const app = new Koa2() // 异常处理 app.use(async (ctx, next) => { try { await next() } catch (error) { ctx.body = { status: ctx.status, message: error.message } ctx.status = 200 } }) // Console app.use(koaLogger()) // code ...
此时再访问 http://localhost:9000/error 会发现状态码已变成200,且错误信息放在JSON格式的响应数据中。
至此,我们已经了解了Koa2
框架以及中间件的基本工作原理。
下一章将会给大家讲解项目的目录结构,以及 MVC
模式的变形及应用。