Skip to content

Commit

Permalink
feat: asyncFlow and asyncFlowRight methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Milishchuk committed Apr 11, 2024
1 parent c7c70a7 commit 740cdf5
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
55 changes: 55 additions & 0 deletions src/asyncFlow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Composes a function that returns the result of invoking the given functions
* with the `this` binding of the created function, where each successive
* invocation is supplied the return value of the previous.
*
* @since 3.0.0
* @category Util
* @param {IncommingFunction[]} [funcs] The functions to invoke.
* @returns {OutcomingFunction} Returns the new composite function.
* @see asyncFlowRight
* @example
*
* import add from 'lodash/add'
*
* async function square(n) {
* const { resolve } = Promise.withResolvers()
* setTimeout(() => {
* resolve()
* }, 3000);
* }
*
* (async () => {
* const addSquare = asyncFlow(add, square)
*
* const result = await addSquare(1, 2)
* console.log(result) => 9
* })()
*/

type IncommingFunction = (...args: any[]) => Promise<any> | any;
type OutcomingFunction<T> = (...args: any[]) => Promise<T>;

export function asyncFlow<T>(funcs: IncommingFunction[]): OutcomingFunction<T> {
const length = funcs.length;
let i = funcs.length;

while (i--) {
if (typeof funcs[i] !== 'function') {
throw new TypeError('Expected a function');
}
}

return async function (this: any, ...args: any[]) {
let j = 0;
let result = length ? await funcs[j].apply(this, args) : args[0];

while (++j < length) {
result = await funcs[j].call(this, await result);
}

return result;
};
}

export default asyncFlow;
39 changes: 39 additions & 0 deletions src/asyncFlowRight.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import asyncFlow from './asyncFlow.js';

/**
* Composes a function that returns the result of invoking the given functions
* with the `this` binding of the created function, where each successive
* invocation is supplied the return value of the previous.
*
* @since 3.0.0
* @category Util
* @param {IncommingFunction[]} [funcs] The functions to invoke.
* @returns {OutcomingFunction} Returns the new composite function.
* @see asyncFlow
* @example
*
* import add from 'lodash/add'
*
* async function square(n) {
* const { resolve } = Promise.withResolvers()
* setTimeout(() => {
* resolve()
* }, 3000);
* }
*
* (async () => {
* const addSquare = asyncFlowRight(square, add)
*
* const result = await addSquare(1, 2)
* console.log(result) => 9
* })()
*/

type IncommingFunction = (...args: any[]) => Promise<any> | any;
type OutcomingFunction<T> = (...args: any[]) => Promise<T>;

export function asyncFlowRight<T>(funcs: IncommingFunction[]): OutcomingFunction<T> {
return asyncFlow<T>([...funcs.reverse()]);
}

export default asyncFlowRight;

0 comments on commit 740cdf5

Please sign in to comment.