【后端基础扫盲】koa洋葱圈原理

首先平时我们写middle ware都是像下面这样对不对?

async function fn1(next) {
    console.log('fn1')
    await next()
    console.log('end fn1')
}

async function fn2(next) {
    console.log('fn2')
    await next()
    console.log('end fn2')
}

async function fn3(next) {
    console.log('fn3')
    console.log('end fn3')
}

next方法是koa框架给我们的工具,那如果没有这个next我们怎么才能一层层调用下一个方法呢?我首先想到的就是 await/async,那就去掉next方法并自己动手改造一下!代码如下:

async function fn1(nextMiddleWarePointer) {
    console.log('fn1')
    if(nextMiddleWarePointer)
    {
        await nextMiddleWarePointer();
    }
    console.log('end fn1')
}

async function fn2(nextMiddleWarePointer) {
    console.log('fn2')
    if(nextMiddleWarePointer)
    {
        await nextMiddleWarePointer();
    }
    console.log('end fn2')
}

async function fn3(nextMiddleWarePointer) {
    console.log('fn3')
    if(nextMiddleWarePointer)
    {
        await nextMiddleWarePointer();
    }
    console.log('end fn3')
}

fn1(function(){
    return fn2(function(){
        return fn3()
    })
} )

这个代码很容易理解,一个个中间件就像被一条链子穿起来一样,为了可以让当前的中间件可以调用下一个中间件我至少得把下一个中间件的引用传给它,就比如我想让fn2调fn3,我就得把fn3的引用当做参数传给fn2,上面代码中nextMiddleWarePointer就是下一个中间件的引用。最后在调用这个中间件链的时候,写法必然是一层套一层的,并且因为我们是把函数当做引用传进去供其调用,所以要在fn外面套一层函数,避免被直接调用。

下面开始优化上面代码,既然代码中出现了层层嵌套的写法那就必然可以替换成递归!下面就把它改造成递归。代码如下:

function compose(middleWareArray) {
    return function () {
        dispatch(0);
        function dispatch(nextIndex) {
            const fn = middleWareArray[nextIndex];
            if (fn) {
                return new Promise((resolve) => {
                    resolve(fn(function () {return dispatch(nextIndex + 1) }));
                })
            }
            else {
                return function () { };
            }
        } 
    }
}

async function fn1(nextMiddleWarePointer) {
    console.log('fn1')
    await nextMiddleWarePointer();
    console.log('end fn1')
}

async function fn2(nextMiddleWarePointer) {
    console.log('fn2')
    await nextMiddleWarePointer();
    console.log('end fn2')
}

async function fn3(nextMiddleWarePointer) {
    console.log('fn3')
    await nextMiddleWarePointer();
    console.log('end fn3')
}

middleWareArray = [fn1, fn2, fn3];
const startFn = compose(middleWareArray);
startFn();

最后把compose函数再改造一下,如下:

function compose(middleWareArray) {
    return function () {
        dispatch(0);
        function dispatch(nextIndex) {
            const fn = middleWareArray[nextIndex];
            if (fn) {
                return Promise.resolve(fn(function () {return dispatch(nextIndex + 1) }));
            }
            else {
                return Promise.resolve();
            }
        }
    }
}

这个代码其实有不少值得细细玩味的地方,大家自行研究吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值