React之reduce实现compose和中间件

reduce实现compose和中间件

函数的深度嵌套调用

通常当下一个调用的函数需要使用到上一个函数执行结果的时候,我们一般会这么做:

例如 吃一次饭:

javascript 复制代码
// 买食物
function buyFood(moeny) {
    return 'original food'
}
// 处理食材
function dealFood(originalFood) {
    return 'ingredients'
}
// 烹饪
function cookFood(ingredients) {
    return 'food'
}
// 吃
function eat(food){}

我们大约需要经历这些步骤,那么一次午饭我们这样:eat(cookFood(dealFood(buyFood(moeny)))),吃一次晚饭:eat(cookFood(dealFood(buyFood(moeny))))...

这种方式不仅增大代码量,更增加阅读和维护的难度;如果业务突然有了改动:一家人吃饭,你怎么能做好了自己就开吃,你得喊家人一起吃对吧?

那么烹饪和吃之间我们需要加一个:

javascript 复制代码
// 喊家人吃饭
function callFamily(ingredients){
    return 'Family'
}

更好得方式肯定是整合封装一下:

javascript 复制代码
function eatMeal(money){
    return eat(cookFood(dealFood(buyFood(moeny))))
}

这样调用的时候,也只需要eatMeal(money),需要callFamily也能直接修改eatMeal即可。但是这样,如果更多的嵌套,就有更多的层叠关系。而我们希望通过类似这样的关系来描述:step1 => step2 => step3 ..

通过reduce实现compose

javascript 复制代码
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

我们需要的结果类似这样:

javascript 复制代码
[step1,step2,step3,step4 ... ].reduce(function(arg,fn){
    return fn(arg)
},arg)

传入一个参数arg,顺序执行数组中的函数,并且后续每一次的入参都是上一步的结果,执行完毕后返回结果。

封装一下:

javascript 复制代码
function compose(fns, arg) {
    Array.prototype.reduce.call(fns, (pre, cur) => {
        return cur(pre)
    }, arg)
}
compose([step1,step2,step3],arg)

但是和第一次问题一样,每一次调用都必须带上所有步骤,不利于编码和维护。

我们需要的是一次定义,多次调用时候只传入参数:

javascript 复制代码
function compose() {
    var fns = arguments;
    return function (arg) {
        return Array.prototype.reduce.call(fns, (pre, cur) => {
            return cur(pre)
        }, arg)
    }
}
function add(num) {
    var result = num + 1;
    console.log(result)
    return result;
}
var add3Times = compose(add, add, add)
console.log(add3Times(2))

再对比网上流传的compose:

javascript 复制代码
function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

多了两个判断:判断没有传入的函数和传入一个函数的时候处理,并且和上面的实现不同,reduce每一步返回的并不是上一步的结果,而是一个函数,最后一样返回一个函数。

第一种情况返回的函数中,函数体内包括reduce的执行,所以后续每次调用都需要重新reduce然后返回结果,并且因为占用arguments,所以compose的执行栈也会一直存在内存中;而第二种返回的是已经经过reduce组装之后的函数,不再占用,所以原来的执行栈可以释放。

修改一下:

javascript 复制代码
function compose() {
    var fns = arguments;
    return Array.prototype.reduce.call(fns, (pre, cur) => {
        return (arg) => {
            return cur(pre(arg))
        }
    })
}

中间件

中间件就是一个函数,可以通过中间件组合成一个最终你想要的逻辑函数。

相关推荐
志尊宝1 小时前
AI原生前端开发(031):AI辅助的性能分析与瓶颈定位
javascript·人工智能·ai-native
adinnet20261 小时前
持续智能问数:多轮对话状态管理、下钻钻取与经营驾驶舱的演进
javascript·数据库·人工智能
FYKJ_20101 小时前
springboot高考志愿填报推荐系统14332-计算机课程设计、毕业设计
javascript·spring boot·python·架构·django·课程设计·高考
全栈若城1 小时前
从源码拆解一个 AIUI 每日一词智能体:页面、离线索引与硬件交互
javascript
DataGear1 小时前
DataGear 6.1.1 发布,数据可视化分析平台
javascript·信息可视化·数据分析·echarts·数据可视化
Dumbness1 小时前
农历转换的 4 个边界:2 月 30 日能转出"正月十四"、小月没有三十、闰月、立春到春节之间的干支
前端·javascript
系统集成-鹰翔2 小时前
ERP接口月度统计少了零单月份:SQLite分组与最近三个月均值排查
javascript·数据库·经验分享·后端
mONESY2 小时前
从线性 RAG 到 Agentic RAG|基于 LangGraph 实现自主决策 RAG 闭环
javascript·面试
可乐_不渴2 小时前
【Linux】 进程虚拟地址空间
java·linux·javascript
vipxieliang2 小时前
JavaScript 深浅拷贝全解析:从 JSON 到 structuredClone
前端·javascript