洋葱模型
redux Express Koa在处理中间件的时候,逻辑类似,都用到了compose方法
compose(ctx) {
let middlewares = this.middlewares
let idx = -1;
function dispatch(i) {
// 没有中间件直接成功
if (i <= idx) return Promise.reject(new Error('next() call multiple times'))
if (i === middlewares.length) return Promise.resolve()
let fn = middlewares[i];
idx = i
// 我们将用户的函数包装了promise
// 而且是一个链式的调用
try {
// 可能用户提供的是一个普通的函数,此时没办法通过promise 来进行捕获,所以要直接try catch
return Promise.resolve(fn(ctx, () => dispatch(i + 1)))
} catch (err) {
return Promise.reject(err)
}
}
return dispatch(0)
}
handleRequest = (req, res) => {
// 每次请求都是独立的, 不会出现 不同的请求 复用属性
const ctx = this.createContext(req, res)
res.statusCode = 404;
this.compose(ctx).then(() => {
let body = ctx.body;
if (typeof body === 'string' || Buffer.isBuffer(body)) {
res.end(body)
} else {
res.end('Not Found')
}
}).catch(err => {
this.emit('error', err)
})
}
每次请求过来时,会走handleRequest方法,然后就通过dispatch(0)触发整个调用链