两分钟搞懂从函数组合到中间件实现

本文涉及的产品
云原生网关 MSE Higress,422元/月
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 很多JS框架中都会用到中间件,形成一个洋葱圈结构,这样可以很好的应付业务逻辑中的对于切面描述的需要。 经典案例比如Redux 中间件和Koa 中间件

很多JS框架中都会用到中间件,形成一个洋葱圈结构,这样可以很好的应付业务逻辑中的对于切面描述的需要。 经典案例比如Redux 中间件和Koa 中间件


1.无组合状态


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


这个其实不能叫做组合 只是程序先运行最内层的表达式 然后向外运行 实际上这个执行顺序就是 fn1 -> fn2 -> fn3 执行结果如下:


fn1
end fn1
fn2
end fn2
fn3


当然这个里面你即使写await执行顺序也没有什么变化


(async () => {
    await fn3(await fn2(await fn1()))
})()


2.两个函数的组合


下面我们通过参数传递的方式把两个函数组合成一个函数。


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


执行结果如下


fn2
fn1
end fn1
end fn2


3 多个函数的组合


影响多个函数不能串行的原因是 fn2的中不能返回函数结果。 解决这个问题的方法是不要函数的运行结果而是将函数科里化后返回


async function fn1(next){
    console.log('fn1')
    next && await next()
    console.log('end fn1')
}
async function fn2(next){
    console.log('fn2')
    next && await next()
    console.log('end fn2')
}
async function fn3(next){
    console.log('fn3')
    next && await next()
    console.log('fn3')
}
async function fn4(next){
    console.log('fn4')
    next && await next()
    console.log('fn4')
}
fn1(() => fn2(() => fn3(fn4)))


看一下执行结果


fn1
fn2
fn3
fn4
fn4
fn3
end fn2
end fn1


4.通用异步Compose函数


最后我们将这个操作写成一个通用函数


const compose = (...args) =>  {
    [first,...others] = args.reverse()
    let ret = first
    others.forEach(fn => {
        let retOld = ret
        ret = () => fn(retOld)
    })
    return ret
}
compose(fn1,fn2,fn3,fn4)()


相关文章
|
消息中间件 JSON 中间件
你用Go写过中间件吗?带你用Go实现【操作日志中间件】
管理后台所有修改,添加,删除的操作都要记录;操作日志的统计不影响主程序的性能
562 9
你用Go写过中间件吗?带你用Go实现【操作日志中间件】
|
中间件 uml
阿里中间件seata源码剖析六:TCC模式中2阶段提交实现
阿里中间件seata源码剖析六:TCC模式中2阶段提交实现
384 6
阿里中间件seata源码剖析六:TCC模式中2阶段提交实现
|
中间件 程序员 Go
你用Go写过中间件吗?带你用Gin实现【用户角色权限管理中间件】
管理后台有超管权限,超管拥有所有权限;普通管理员可以设置角色,角色单选;角色可以赋予多个权限,权限多选;这样我们就实现了对普通管理员的角色和权限的灵活管理
346 7
你用Go写过中间件吗?带你用Gin实现【用户角色权限管理中间件】
|
中间件 Python
Python编程:Django中间件实现登陆验证
Python编程:Django中间件实现登陆验证
191 5
Python编程:Django中间件实现登陆验证
|
消息中间件 设计模式 缓存
天天造轮子第七天 - 中间件实现 - Compose 的 N 种姿势
天天造轮子第七天 - 中间件实现 - Compose 的 N 种姿势
226 6
|
中间件 Java Spring
从-1开始实现一个中间件
别人都写从0开始实现xxx,我先从-1开始就显得更牛逼一些。 今天,先开个头,来教大家怎么实现一个中间件。
183 6
从-1开始实现一个中间件
|
存储 分布式计算 监控
阿里云互联网中间件:让企业实现业务云化持续创新|学习笔记
快速学习 阿里云互联网中间件:让企业实现业务云化持续创新
216 7
|
编解码 运维 监控
电商直播平台如何借助容器与中间件实现研发效率提升100%?
经过实际场景验证及用户的综合评估,电商直播平台借助全面的云原生容器化能力和中间件产品能力,大幅提升开发部署运维效率达50%~100%,极大地提升了用户体验,为业务持续发展打下了坚实的基础。
7256 5
电商直播平台如何借助容器与中间件实现研发效率提升100%?
|
存储 JavaScript NoSQL
SpringBoot2 整合MinIO中间件,实现文件便捷管理
MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
771 7
SpringBoot2 整合MinIO中间件,实现文件便捷管理
|
消息中间件 Prometheus Cloud Native
阿里云原生中间件首次实现自研、开源、商用“三位一体”,技术飞轮效应显现
阿里云在探索中一直存在的苦恼,是内部的自研体系、商业化的产品技术与开源的项目,三方的技术路线一直没有机会融为一体。然而,就在今年阿里云提出了“三位一体”理念,即将“自研技术”、“开源项目”、“商业产品”形成统一的技术体系,最大化技术的价值。
阿里云原生中间件首次实现自研、开源、商用“三位一体”,技术飞轮效应显现