ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 介绍 提到 Node.js 开发,不得不提目前炙手可热的两大框架 Express 和 Koa。 Express 诞生已有时日, 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,主要基于 Connect 中间件,并且自身封装了路由、视图处理等功能,使用人数众多。 Koa 相对更为年轻, 是 Express 原班人马基于 ES7 新特性重新开发的框架,框架自身不包含任何中间件,很多功能需要借助第三方中间件解决,但是由于其基于 ES7 async 特性的异步流程控制,解决了 "callback hell" 和麻烦的错误处理问题,大受开发者欢迎。Koa 目前已经升级到了 2.x,以下代码示例都会使用 Koa 2.x。 ## 示例 ### Hello World 两者创建一个基础的 Web 服务都非常简单,写法也基本相同,最大的区别是路由处理 Express 是自身集成的,而 Koa 需要引入中间件。 ~~~ // Express const express = require('express') const app = express() app.get('/', function (req, res) { res.send('Hello Express') }) app.listen(3000) ~~~ ~~~ // Koa const Koa = require('koa') const route = require('koa-route') const app = new Koa() app.use(route.get('/', async (ctx) => { ctx.body = 'Hello Koa' })) app.listen(3000) ~~~ ### Views Express 自身集成了视图功能,提供了 consolidate.js 功能,支持几乎所有 JavaScript 模板引擎,并提供了视图设置的便利方法。 Koa 需要引入 koa-views 中间件。 ~~~ // Express const express = require('express') const app = express() app.set('views', __dirname + '/views') app.set('view engine', 'pug') app.get('/', function (req, res) { res.render('index', { title: 'Express' }) }) ~~~ ~~~ // Koa const Koa = require('koa') const route = require('koa-route') const views = require('koa-views') const app = new Koa() app.use(views(path.join(__dirname, './views'), { extension: 'pug' })) app.use(route.get('/', async (ctx) => { await ctx.render('index', { title: 'Koa' }) })) ~~~ ## 区别 ### 中间件模型 Koa 的中间件采用了洋葱圈模型,所有的请求在经过中间件的时候都会执行两次,能够非常方便的执行一些后置处理逻辑。 例如,我们经常需要计算一个请求的响应时间,在 Koa 中, 我们可以在中间件的开始记录初始时间,当响应返回时,代码执行又回到了原来的中间件,此时根据当前时间和初始时间的时间差便得到了响应时间。 ~~~ function responseTime() { return async function responseTime(ctx, next) { const start = Date.now() await next() // wait for other middleware to run const delta = Math.ceil(Date.now() - start) ctx.set('X-Response-Time', delta + 'ms') }) }} ~~~ 而在 Express 中,响应返回时代码执行并不会回到原来的中间件,此时我们需要通过监听`response.writeHead`获得响应返回的时机: ~~~ const onHeaders = require('on-headers') function responseTime () { return function responseTime (req, res, next) { const startAt = process.hrtime() onHeaders(res, function onHeaders () { const diff = process.hrtime(startAt) const time = diff[0] * 1e3 + diff[1] * 1e-6 res.setHeader('X-Response-Time', time + 'ms') }) next() } } ~~~ ### 异常处理 Express 使用 Node 约定的 "error-first 回调" 处理异常,并通过中间件传播。 Koa 通过同步方式编写异步代码,可以通过`try catch`处理异常,非常自然。 ~~~ // Express app.use(function (err, req, res, next) { res.status(err.status || 500).send('error') }) ~~~ ~~~ // Koa app.use(async (ctx, next) => { try { await next() } catch (err) { ctx.app.emit('error', err) ctx.status = err.status || 500 ctx.body = { message: err.message } } }) ~~~ ### Context Koa 新增了一个 Context 对象,用来代替 Express 中的 Request 和 Response,作为请求的上下文对象。 Context 上除了 Request 和 Response 两个对象之外,还有 Node.js 原生提供的 req 、res、socket 等对象。