Koa2——洋葱模型,简单实现

class app {
    middleware = [];

    // 装载中间件
    use(middleware) {
        this.middleware.push(middleware);
    }

    compose(callback) {
        // 把 要被触发的上一层洋葱壳 作为下一层洋葱壳的next入参传入。
        // reducer 的返回值,也就是下一层的next为 () => fn(next)。
        const reducer = (next, fn) => () => fn(next);

        // 第二个参数为洋葱的中心;可传入任意函数。(但必须传入函数)
        this.middleware.reduceRight(reducer, callback)();
    }
}

 调用方法

const app = new app();

function middleware1(next) {
    console.log('come in 1');
    next();
    console.log('come out 1'); 
}

function middleware2(next) {
    console.log('come in 2');
    next();
    console.log('come out 2'); 
}

function middleware3(next) {
    console.log('come in 3');
    next();
    console.log('come out 3'); 
}

app.use(middleware1);

app.use(middleware2);

app.use(middleware3);

app.compose(() => console.log('call controller'));

执行结果为

come in 1
come in 2
come in 3
call controller
come out 3
come out 2
come out 1

 

上述代码执行后 middleware为[middleware1, middleware2, middleware3];

reduceRight生成的函数为

() => middleware1(() => middleware2(() => middleware3(callback)))

compose被调用后

首先执行middleware1 打印 come in 1
然后执行至 middleware1的next

接下来就执行middleware2 middleware3

当执行至middleware3的next时,洋葱中心的callback被调用
所有next执行完毕
此时 middleware3 的 next() 之后的逻辑是 console.log('come out 3')
打印 come out 3 后,middleware3 执行完成
middleware3 执行完成则表示 middleware2 的 next() 执行完成
接下来执行middleware2 的 next() 后的逻辑
最后是 middleware1 的 next() 之后的逻辑。

整个过程就像 一只虫子进入一个洋葱之中,洋葱从外到里一层一层地打开, 离开之后洋葱又从里到外一层一层地关闭。

你可能感兴趣的:(javascript,1024程序员节)