洋葱模型 compose方法
如果中间件场景中不存在前后依赖的情况,从头到尾按顺序链式调用完全没有问题,但如果存在依赖情况呢? 如果只链式执行一次,无法保证前面的中间件能使用之后中间件添加的东西。
同步版本
class Koa {constructor() {this.middlewares = []}use (fn) {this.middlewares.push(fn)}compose () {function dispatch(index) {// 如果所有中间件都执行完跳出if (index === app.middlewares.length) return// 取出第 index 个中间件并执行const fn = app.middlewares[index]// () => dispatch(index + 1),这其实就是next方法return fn(() => dispatch(index + 1))}dispatch(0);}}// 调用const app = new Koa()app.use((next) => {console.log(1)next()console.log(2)})app.use((next) => {console.log(3)next()console.log(4)})app.use((next) => {console.log(5)next()console.log(6)})app.compose()
由于下一个中间件,作为上一个中间件的next参数传入,使得上面的代码输出为 1,3,5,6,4,2
异步版本
正常情况下,如果中间件为异步(涉及到数据库读取操作,请求远程资源的),我们会用 await next()
需要修改下同步版本,使同步版本返回一个 Promise 即可,如下
class Koa {constructor() {this.middlewares = []}use (fn) {this.middlewares.push(fn)}compose () {function dispatch(index) {// 如果所有中间件都执行完跳出if (index === app.middlewares.length) return Promise.resolve()// 取出第 index 个中间件并执行const fn = app.middlewares[index]// () => dispatch(index + 1),这其实就是next方法return Promise.resolve(fn(() => dispatch(index + 1)))}dispatch(0)}}const app = new Koa()app.use(async (next) => {console.log(1)await next()console.log(2)})app.use(async (next) => {console.log(3)await next()console.log(4)})app.use(async (next) => {console.log(5)await next()console.log(6)})app.compose()
