koa核心

Keep learning

中间件框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 搭一个Server
const Koa = require('koa')
const router = require('koa-router')()
const app = new Koa()

router.get('/article', ctx => {
let article = fetchArticleFromDB(ctx.query.id)
ctx.body = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF=8">
<title>${article.title}</title>
</head>
<body>
<div class="article">
${article.content}
</div>
</body>
</html>`
})
app.use(router.routes())
app.listen(3000)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
listen(...args) {
const server = http.createServer(this.callback());
return server.listen(...args);
}

callback() { // compose = middleware => ctx => Promise
const fn = compose(this.middleware);

const handleRequest = (req, res) => {
const ctx = this.createContext(req, res);
return this.handleRequest(ctx, fn);
}

return handleRequest;
}

handleRequest(ctx, fnMiddleware) {
const onerror = err => ctx.onerror(err);
const handleRequest = () => respond(ctx);
return fnMiddleware(ctx).then(handleRequest).catch(onerror);
}
1
2
3
4
5
// use 的作用
use(fn) {
this.middleware.push(fn);
return this;
}
1
2
3
4
5
6
7
8
9
10
11
// 中间件的执行
async (ctx, next) => {
// before

await next()

//after
}
app.use(middleware1)
app.use(middleware2)
app.use(middleware3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// middleware机制
function compose(middleware) {
return function(context, next) {
// last called middleware
let index = -1
return dispatch(0)
function dispatch(i) {
if(i <= index) return Promise.reject(new Error('next() called multiple times'))
index = i
let fn = middleware[i]
if(i === middleware.length) fn = next
if(!fn) return Promise.resolve()
try {
return Promise.resolve(fn(context), dispatch.bind(null, i + 1))
} catch (err) {
return Promise.reject(err)
}
}
}
}

context

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Context的封装
// request response
createContext(req, res) {
const context = Object.create(this.context);
const request = context.request = Object.create(this.request);
const response = context.response = Object.create(this.response);
context.app = request.app = response.app = this;
context.req = request.req = response.req = req;
context.res = request.res = response.res = res;
request.ctx = request.ctx = context;
request.response = response;
response.request = request;
context.originalUrl = request.originalUrl = req.url;
context.cookies = new Cookies(req, res, {
keys: this.keys,
secure: request.secure
});
request.ip = request.ips[0] || req.socket.remoteAddress || '';
context.accept = request.accept = accepts(req);
context.state = {};
return context;
}