koa洋葱模型原理

2020-09-12  本文已影响0人  赵永盛
async function m1(next) {
    console.log('m1')

    await next()

    console.log('e')
}

async function m2(next) {
    console.log('m2')

    await next()

    console.log('d')
}

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

const next3 = async () => {
    m3()
}

const next2 = async () => {
    m2(next3)
}

const next1 = async () => {
    m1(next2)
}

next1()

// 输出:
// m1
// m2
// m3
// d
// e

首先,关于 洋葱模型 自上而下-》自下而上 回溯机制并不是 koa 自己的特性,而是 async/await 自己执行顺序的特定,就是 async/await 自带这个特性

可以写个 demo 验证一下:

async function a1() {
    console.log('a1')
    await a2()
    console.log('a3')
}

async function a2() {
    console.log('a2')
}

a1()
// 输出
// a1
// a2
// a3

也就是, await 执行时,会先去执行后面的 异步函数,等待后面 异步函数有了结果,才会继续执行 await 后面的代码,自己本身就具有 “回溯机制”

koa 只是做了一件事,就是 创建了 next 函数,这个函数的作用就是调用下一个中间件

下一个中间件同样需要 next 参数,所以我们需要依照中间件列表倒序构建 next 函数,先构建最后一个中间件需要的 next 函数,然后再构建倒数第二个中间件需要的 next 函数...以此类推

最后呢,所有中间件就构成了一条链。我们调用链开头的 next 函数,每个链条节点中又调用

await next()

调用下一个中间件,最终所有中间件都得到了执行。

构建 next 函数我们可以封装一下,是这个样子:

function createNext (middleware, oldNext) {
    return async () => {
        await middleware(ctx, oldNext)
    }
}

const len = this.middlewares.length;
let next = async () => {
    return Promise.resolve()
}

for (let i = len - 1; i >= 0; i--) {
    let currentMiddleware = this.middlewares[i]
    next = createNext(currentMiddleware, next)
}

await next()

同时,为了使最后一个中间件也有 next 参数,我们可以创造一个空的 async 函数

const next = async () {}
//...
m3(next)
上一篇下一篇

猜你喜欢

热点阅读