封装了http,特点是中间件和错误处理
用法
let koa = require('koa')
let app = new koa()
app.use(async (ctx,next)=>{ // 洋葱模型 // 1
console.log('第1个开始');
let t = await next()
console.log(t);
return '第1个结束'
});
app.use(async (ctx,next)=>{ // 2
console.log('第2个开始');
await logger();
let t = next()
console.log(t);
return '第2个结束'
});
app.use(async (ctx,next)=>{ // 3
console.log('第3个开始');
//next();
ctx.body = 'ok';
return '第3个结束'
});
app.listen(3000);
中间件的特点是洋葱模型(为保运行结果在预期内,尽量使用async函数)
简单实现
// mykoa.js
let http = require('http')
let content = require('./context')
let stream = require('stream')
class mykoa {
constructor () {
this.middlewares = []
this.server = http.createServer(this.Handler.bind(this))
}
async compose (ctx) {
// 以洋葱模型执行中间件
let t = this.middlewares.reduceRight((prev, fn) => {
return async () => {
if (prev.is_called == 'yes') {
throw new Error('next 只能调用一次')
}
prev.is_called = 'yes'
return await fn(ctx, prev)
}
}, () => {});
await t();
}
async Handler (req, res) {
let ctx = {}
try {
content.call(ctx, req, res)
// 处理中间件
await this.compose(ctx)
if (ctx.body) {
// console.log('** end **')
res.statusCode = 200;
if (ctx.body instanceof stream) { // body里是流当做下载
res.setHeader("Content-Disposition","attachment;filename="+encodeURI('下载'));
ctx.body.pipe(res)
} else {
res.end(ctx.body)
}
}
else throw new Error('body is empty')
} catch (e) {
console.error(e)
res.statusCode = 404;
res.end('Not Find')
}
}
use (fn) {
this.middlewares.push(fn)
}
listen (port) {
this.server.listen(port)
}
}
module.exports = mykoa
// context.js 添加koa自有参数
module.exports = function (req, res) {
this.req = req
this.res = res
this.request = Object.create(req)
this.response = Object.create(res) // 链上多套一层
this.url = req.url
let _body = null
let attributes = {
get () { return _body },
set (val) { _body = val; }
}
Object.defineProperty(this.response, 'body', attributes)
Object.defineProperty(this, 'body', attributes)
if (req.method == 'POST') {
res.setHeader('Content-Type', 'application/json;charset=utf-8')
} else if (req.method == 'Get') {
res.setHeader('Content-Type', 'text/html;charset=utf8')
}
}
常用包
- koa-bodyParser
- koa-static
- koa-views
- koa-router
- koa-generator koa脚手架
-
koa mypro -e
创建一个ejs项目