函数组合与管道的核心是让数据顺序流经专注的单职责函数,pipe从左到右执行(如pipe(f,g,h)(x)≡h(g(f(x)))),推荐优先使用;基础pipe用reduce实现,支持一元纯函数串联;pipeasync则通过promise链支持异步流程。

理解方向:右到左 vs 左到右
函数组合(compose)默认从右向左执行:输入先被最右边的函数处理,结果依次向左传递。例如 compose(f, g, h)(x) 等价于 f(g(h(x)))。
管道(pipe)则相反,更贴近自然阅读习惯:从左到右执行,pipe(f, g, h)(x) 等价于 h(g(f(x)))。
二者本质相同,只是调用顺序镜像对称。推荐优先使用 pipe,尤其在多步骤数据流中,逻辑走向与代码书写顺序一致,不易出错。
实现一个可靠的基础 pipe 函数
用 reduce 实现左到右串联,要求所有函数都是一元纯函数(只接受一个参数,无副作用):
const pipe = (...fns) => (value) => fns.reduce((acc, fn) => fn(acc), value);
- 传入多个函数,返回一个新函数
- 该新函数接收初始值,逐个应用每个函数
- 中间结果自动传递,无需临时变量
实际串联示例:处理用户姓名
假设要对原始字符串做三步处理:去空格 → 转大写 → 加感叹号:
const trim = s => s.trim();
const toUpper = s => s.toUpperCase();
const addExcl = s => s + '!';
const formatName = pipe(trim, toUpper, addExcl);
console.log(formatName(" hello world ")); // "HELLO WORLD!"
每一步都独立可测、可复用;组合后语义清晰,一眼看出数据流向。
延伸:支持异步的 pipeAsync
当流程涉及 Promise(如 API 请求),只需稍作调整:
const pipeAsync = (...fns) => (value) => fns.reduce((p, fn) => p.then(fn), Promise.resolve(value));
- 每个函数必须返回 Promise
- 前一个的 resolve 值自动作为下一个的输入
- 错误会自然沿链路抛出,可用
.catch统一处理











