函数调用中间件的理解和基本代码实现

270 阅读1分钟

一般我们调用一个功能函数之前会对这个调用请求做一些预处理,有的时候还需要对功能函数的返回值进行后处理。这样就形成了两种调用业务流程。一种是顺序调用又称为洋葱模型(核模型),这种模型同时进行前处理和后处理。另外一种单纯的前处理又称单向向调用模型(壳模型)。下面将具体解析和实现这两种模型。

  • 单向调用模型(壳模型) 特点:功能函数位于调用链的最外层(壳层),后续中间件调用前序的返回值,功能函数调用前序后随即返回输出。

    MA,MB,MC代表中间件函数,FF代表功能函数

graph TD
INPUT -->MA --> MB -->MC --> FF -->OUTPUT

这种调用流程中 OUTPUT=FF(MC(MB(MA(INPUT)))),此时调用方向是最外层往内核调用,功能函数位于调用的最外层。

无标题绘图.svg

  • 洋葱模型(核模型)----功能函数调用位于最内层(核层) 特点:调用流程是先序中间件调用后续中间件直到功能函数调用然后反向返回。

无标题绘图 (1).svg

示例代码:

    console.log('pre A start')
    console.log(ctx)
    console.log('pre a finish')
    next(ctx)
    console.log('after a start')
    console.log(ctx)
    console.log('after A finish')
}

const mB = (ctx,next) => {
    console.log('pre B start')
    console.log(ctx)
    console.log('pre B finish')
    next(ctx)
    console.log('after B start')
    console.log(ctx)
    console.log('after B finish')
}
const mC = (ctx,next) => {
    console.log('pre C start')
    console.log(ctx)
    console.log('pre C finish')
    next(ctx)
    console.log('after C start')
    console.log(ctx)
    console.log('after C finish')
}

const f1 = (ctx) => {
    console.log('this is f1')
}
const f2 = (ctx) => {
    console.log('this is f2')
}
const f3 = (ctx) => {
    console.log('this is f3')
}
// let mds = [mA, mB, mC]
// let current=0

function next(ctx) {
    ctx.current++
    if (ctx.current < ctx.mds.length) {

        ctx.mds[ctx.current](ctx,next)

    }
    else {
        ctx.f(ctx)
    }
}
function start(ctx,f) {
    ctx.current=-1
    ctx.mds=[mA, mB, mC]
    ctx.f=f
    console.log(ctx.mds)
    // current = -1;
    next(ctx)
}

start({value:5},f2)
`
```