pipeAsync
Composes async and sync functions from left to right.
1/**
2 * Composes async and sync functions from left to right.
3 *
4 * @param funcs - An array of functions (sync or async).
5 * @returns A function that returns a Promise resolving to the final result.
6 *
7 * @example
8 * const double = async (x: number) => x * 2;
9 * const square = (x: number) => x * x;
10 * const result = await pipeAsync(double, square)(3); // (3 * 2)^2 = 36
11 */
12export function pipeAsync<T>(
13 ...funcs: Array<(arg: any) => any | Promise<any>>
14): (input: T) => Promise<any> {
15 return async (input: T) => {
16 let result = input;
17 for (const fn of funcs) {
18 result = await fn(result);
19 }
20 return result;
21 };
22}
Supports Mixed Sync and Async Functions
Seamlessly composes both synchronous and asynchronous operations into a unified, promise-based pipeline.
Left-to-Right Execution Order
Applies functions in intuitive order, enhancing readability and predictability of data flow.
Automatic Promise Handling
Uses
await
internally to handle any mix of sync and async return values without requiring external wrapping.Versatile and Flexible
Accepts any number of unary functions, enabling complex dynamic pipelines for processing streams, data, or user input.
Tests | Examples
1test('pipeAsync - applies async and sync functions in order', async () => {
2 const double = async (x: number) => x * 2;
3 const square = (x: number) => x * x;
4 const addOne = async (x: number) => x + 1;
5
6 const fn = pipeAsync(double, square, addOne);
7 const result = await fn(2); // ((2 * 2)^2) + 1 = 17
8 expect(result).toBe(17);
9});
10
11test('pipeAsync - works with only sync functions', async () => {
12 const fn = pipeAsync(
13 (x: string) => x.length,
14 (len: number) => len * 2
15 );
16 const result = await fn('abc'); // 3 * 2 = 6
17 expect(result).toBe(6);
18});
19
20test('pipeAsync - works with only async functions', async () => {
21 const fn = pipeAsync(
22 async (x: number) => x + 1,
23 async (x: number) => x * 3
24 );
25 const result = await fn(2); // (2 + 1) * 3 = 9
26 expect(result).toBe(9);
27});
28
29test('pipeAsync - works with no functions', async () => {
30 const fn = pipeAsync();
31 const result = await fn('test');
32 expect(result).toBe('test');
33});
Common Use Cases
Async Data Transformation Pipelines
Chain API calls, validators, formatters, or enrichment steps in data processing tasks.
Form Submission and Validation
Process user input with sync validators and async sanitizers (e.g. checking uniqueness via API) in one flow.
Middleware and Request Handling
Compose pre-processing steps for HTTP requests or background jobs that involve both local and remote logic.
ETL and Workflow Systems
Build custom steps for Extract–Transform–Load processes where each step may involve IO or computation.
Reactive Logic and Event Pipelines
Process user actions or system events through a pipeline of business logic, validation, and side effects.