可用reduce实现异步函数串行管道,核心是让前一个promise的resolve值成为下一个函数输入;初始值为promise.resolve(input),累加器始终是promise,每步用.then(fn)链式等待。

可以用 reduce 把多个异步函数串成一条可顺序执行、自动传递结果的管道,核心在于让前一个 Promise 的 resolve 值成为下一个函数的输入。
理解异步函数组合的本质
同步函数组合是 f(g(x)),而异步组合要处理的是 f(g(x)) 中的 g(x) 返回 Promise 的情况。不能直接套用同步 reduce,必须确保每一步都 等待上一步完成再传入下一步。
关键点:
- 初始值通常是一个 Promise(如
Promise.resolve(input)) - 累加器(accumulator)始终是 Promise,不是原始值
- 每个 reducer 函数接收上一步的 Promise 结果,并返回一个新的 Promise
基础异步管道实现
下面是一个最小可用的异步管道执行器:
const pipeAsync = (...fns) => (input) =>
fns.reduce(
(promise, fn) => promise.then(fn),
Promise.resolve(input)
);
使用示例:
const fetchUser = () => Promise.resolve({ id: 123 });
const fetchPosts = (user) => Promise.resolve([{ userId: user.id, title: 'Hello' }]);
const countPosts = (posts) => Promise.resolve(posts.length);
const pipeline = pipeAsync(fetchUser, fetchPosts, countPosts);
pipeline().then(console.log); // 输出: 1
这里 reduce 的第一次迭代:用 Promise.resolve(input) 作为初始值;之后每次调用 .then(fn),把上一步 resolve 的值传给当前 fn,并返回新 Promise —— 自动形成链式等待。
支持中间错误捕获与降级
真实场景中某步可能失败,需要统一处理。可在 reduce 内部用 .catch() 包裹,或让 pipeline 返回带错误处理能力的函数:
const pipeAsyncSafe = (...fns) => (input) =>
fns.reduce(
(promise, fn) =>
promise
.then(fn)
.catch(err => {
console.warn('Pipeline step failed:', err);
throw err; // 或返回默认值:return { error: true, value: null };
}),
Promise.resolve(input)
);
也可扩展为接受 fallback 函数:
const pipeAsyncWithFallback = (fallback, ...fns) => (input) =>
fns.reduce(
(promise, fn) => promise.catch(() => Promise.resolve(input)).then(fn),
Promise.resolve(input)
).catch(fallback);
进阶:支持上下文与多参数注入
若某些异步函数需额外参数(如 API base URL、认证 token),可让 pipeline 接收配置对象:
const pipeAsyncWithContext = (context, ...fns) => (input) =>
fns.reduce(
(promise, fn) => promise.then(result => fn(result, context)),
Promise.resolve(input)
);
这样每个 fn 签名可以是 (value, ctx) => Promise,更灵活地复用逻辑。
不复杂但容易忽略:reduce 本身不关心异步,真正起作用的是 .then() 的链式调度机制 —— 它天然适配 Promise 的扁平化串联,而 reduce 只是帮你省去手写嵌套 .then() 的麻烦。











