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))
        }
    })
}

中间件

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

相关推荐
liangshanbo121511 分钟前
面试题:React 中 Lane 和 Scheduler 是怎么配合的?
前端·react.js·前端框架
liangshanbo121520 分钟前
请求拦截器相关面试题
java·前端·javascript
liangshanbo121522 分钟前
React面试题:Hooks 为什么不能在分支和循环里面写?
前端·javascript·react.js
FungLeo26 分钟前
成为全栈·Next.js 网站前台篇·响应式、可访问性与错误状态:内容站不能只验桌面首页
react.js·响应式设计·next.js·移动端适配·成为全栈·web 可访问性
西红柿炖牛腩35430 分钟前
GLB 转 OBJ/PLY 后体积没变?3D 模型不减面变小靠什么
前端·javascript·3d
ss2731 小时前
AI全栈实战 | 3.5-01 Python 全栈前端最小集:不会 React 也能做出能看的后台,关键就一条线
前端·python·react.js
Ai-_Man1 小时前
从聊天框到正式文档:AI导出鸭瞄准AI大模型应用的“最后一公里”
开发语言·前端·javascript·人工智能·小程序
专业程序开发源2 小时前
springboot酒店会员点餐系统22339-计算机课程设计、毕业设计
java·javascript·vue.js·spring boot·后端·php·课程设计
panxianren9 小时前
Bun 1.4 的 bun test --parallel 将 4 秒的测试套件缩短到约 1 秒
java·javascript
可乐鸡翅yeah_12 小时前
FFmpeg 生成 HLS 独立分片 independent‑segments 参数到底有什么用
javascript·ffmpeg·音视频·safari·m3u8