函数式编程的中从左往右的 pipe 函数和从右往左的 compose 函数,在 js 中的一些应用场景。

# pipe

也称为管道函数,它接受 n 多个函数,依次从左往右执行,用最后一个函数作为最终的输出。用于改善函数嵌套调用,一个简单的示例:

function first (params) {
  return `我是第一个函数,我获取我的参数「${params}」并且返回`
}
function second (params) {
  return `我接受了第一个函数的返回值「${params}」,作为我的参数,然后和我的数据拼接再返回`
}
function end (params) {
  return `我是最后的数据的拼接处理,结合了first函数和second的返回值「${params}`
}

end(second(first(`hi~我来了!💐`)))

最终返回: "我是最后的数据的拼接处理,结合了 first 函数和 second 的返回值「我接受了第一个函数的返回值「我是第一个函数,我获取我的参数「hi ~我来了!💐」并且返回」,作为我的参数,然后和我的数据拼接再返回」"

能看到的是,函数之间形成一种关系,即后一个函数接受上一个函数的返回值作为参数,本例中也就是 end 函数接受 second 的返回值作为参数,而 second 的返回值又是接受 first 的返回值作为参数。

其实能看到 end(second(first()))这么调用嵌套不直观,我们用reduce实现管道 pipe 依次调用。

优化之后的结果:

const pipe = (...arg) => result => arg.reduce((res, callback) => callback(res), result)

调用

pipe(first, second, end)('hi ~我来了!💐')

会将参数先传递给 first,然后处理成功之后,再将结果作为 second 的参数,传递,second 处理完成之后,将结果作为 end 函数的参数,在 end 函数处理完成之后,将所有结果返回。最终 pipe 函数调用的结果,将会上边函数嵌套执行的结果一致。

# compose

组合函数和 pipe 原理都是一样的,只不过是其调用顺序是从右往左。

组合函数在 webpackloader 中也有应用,本例中的 pipe 是从左往右依次执行,webpackloader 是从右向左执行(compose),其实可以利用 reduceRight 实现。

const compose = (...arg) => result => arg.reduceRight((res, callback) => callback(res), result)

这里的话,如果上述的例子是通过 compose 函数来实现的话,应该是 compose(first, second, end)('hi ~我来了!💐'),最外边的参数应该先是给 end 函数,处理完成之后再给 second,最终给 first,由 first 处理,最终返回结果。

# 总结

如果一个数据最终结果,是需要经过很多函数的处理,并且那些函数,需要用上一个函数的返回值作为下一个函数的参数,这种场景下可以考虑使用 pipe 或者 compose 函数来处理,其实使用 pipe 或者 compose 都是可以的,只需要保证传入的函数的顺序是按照数据正确执行的函数顺序即可。

最后更新: 2/12/2023, 7:42:22 AM