Koa的历史
- Express
- 2010.6 TJ开始编写Express
- 2014发展到v0.12,基本成熟,移交StrongLoop
- Koa
- 2013.8 TJ开始编写Koa
- 2015.8 Koa发布v1.0.0版本
- Node.js
- 2013.3 Node.js v0.10发布
- 2014.12 io.js不满Node.js的管理发起分裂
- 2015.2 Node.js v0.12发布
- 2015.9 Node.js与io.js合并为node.js v4.0
Koa开始对Node.js的支持
编程模型不同
- Express的中间件是线性的
- Koa的中间件是U型的
- 对语言特性的使用不同
- Express使用回调函数 next()
- Koa v1.x 使用generator语法
- Koa v2.x 使用async/await语法
- 2011-2016大概率会用Express
- 2017以后 会使用Koa
Koa的中间件模型
U型或洋葱模型$ yarn add koa
$ yarn add --dev @types/koa
$ tsc --init
$ ts-node-dev server.ts
server.ts
import Koa from 'koa'
const app = new Koa()
app.use(async (ctx, next) => {
ctx.body = 'hello'
await next()
ctx.body += ' haha'
})
app.use(async (ctx, next) => {
ctx.body += ' world'
await next()
})
app.use(async (ctx, next) => {
ctx.set('Content-Type', 'text/html;charset=utf-8')
await next()
})
app.listen(3000)
中间件代码
import Koa from 'koa'
const app = new Koa()
app.use(async (ctx, next) => {
await next();
const time = ctx.response.get('X-Response-Time');//读取 response header
console.log(`${ctx.url} - ${time}`);
});
app.use(async (ctx, next) => {
const start = Date.now();//记录开始时间
await next();
const time = Date.now() - start;//记录结束时间 -start=总耗时
ctx.set('X-Response-Time', `${time}ms`);//写到response header里
});
app.use(async ctx => {
ctx.body = 'Hello World';
// 最后一个中间件可以不写 await next()
});
app.listen(3000)
await next()释义
app.use(async (ctx, next) => {
const start = Date.now();
await next(); // ()等待 下一个中间件
const time = Date.now() - start;
ctx.set('X-Response-Time', `${time}ms`);
});
- next()表示进入下一个函数
- 下一个函数会返回一个Promise对象,称为p
- 下一个函数所有代码执行完毕后,将p置为成功
-
awiat next()改写
Promise写法
app.use(async (ctx, next) => {
const start = Date.now();
return next().then(()=>{
const time = Date.now() - start;
ctx.set('X-Response-Time', `${time}ms`);
});
});
一定要写return,因为中间件必返回Promise对象
- 错误处理在这里有点反模式,用app.on(‘error’)更方便一点
Express如何实现Response Time
const express = require('express')
const app = express()
app.use((req, res, next) => {
const start = new Date()
res.locals.start = start
next()
})
app.use((req, res, next) => {
res.write('hello world')
res.end()
next()
})
app.use((req, res, next) => {
const time = new Date().valueOf() - res.locals.start
console.log('time-', time)
})
app.listen(3000)
- 使用response-time库 ```javascript const express = require(‘express’) const responseTime = require(‘response-time’) const app = express()
app.use(responseTime()) app.use((req, res, next) => { res.write(‘hello world’) res.end() next() }) app.use((req, res, next) => { console.log(res.get(‘x-response-time’)) next() }) app.listen(3000, () => { console.log(‘3000’) }) ```
Koa API
app.xxx
app.env app.proxy app.subdomainOffset app.listen() app.callback() app.use(fn) 插入中间件fn app.keys app.context app.on(‘error’,fn) 错误处理 app.emit 触发事件
ctx.xxx
ctx.req Node.js封装的请求 ctx.res ctx.request Koa封装的请求 ctx.response
ctx.state 跨中间件分享数据 ctx.app ctx.cookies.get/set ctx.throw ctx.assert ctx.respond Request委托 Response委托
ctx.request.xxx
request.header request.headers request.method request.length request.url request.origin request.href request.path request.querystring request.search request.host request.hostname request.URL request.type request.charset request.query request.fresh request.stale request.protocol … request.idempotent request.get(field)
ctx.response.xxx
response.header response.headers response.socket response.status response.message response.length response.body x5 response.get() response.set() x2 response.append() response.type response.is() response.redirect(url,[alt]) response.attachment() response.headerSent response.flushHeaders() …
谁在用Koa
egg.js
更推荐
Next.js/Nuxt/Nest