Last active
July 6, 2023 20:12
-
-
Save trozdol/729a3e7b39f5c2e42b57967e89d12912 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Example of a workflow that takes an initial value and | |
| * passes it through a series of functions. Each function' | |
| * output is the input of the next function. The final | |
| * output of the workflow is the output of the last function. | |
| */ | |
| const exampleWorkflowFailure = createWorkflow(addOne, double, wait, square) | |
| exampleWorkflowFailure(5) | |
| .then((result) => { | |
| console.log('exampleWorkflowFailure Result', result) | |
| }) | |
| .catch((err) => { | |
| console.error('exampleWorkflowFailure', err) | |
| }) | |
| const exampleWorkflowSuccess = createWorkflow(wait, addOne, double, square) | |
| exampleWorkflowSuccess(2) | |
| .then((result) => { | |
| console.log('exampleWorkflowSuccess Result', result) | |
| }) | |
| .catch((err) => { | |
| console.error('exampleWorkflowSuccess', err) | |
| }) | |
| /** | |
| * Create a workflow or pipeline of functions that take an input | |
| * and return an output. The output of each function is the input | |
| * of the next function. The last functions result is the final | |
| * output of the workflow. If any function throws an error, the | |
| * workflow stops and the error is thrown. This function accepts | |
| * async functions and functions that return promises. | |
| * | |
| * @param {...Function|AsyncFunction} functions | |
| * @returns {function} A function that takes an initial input and returns a promise that resolves to the final output. | |
| */ | |
| function createWorkflow(...functions) { | |
| return async function workflow(initialInput) { | |
| let error | |
| let result = await functions.reduce(async function (result, fn, fnIndex, fnList) { | |
| let input, output | |
| try { | |
| input = await result | |
| output = await fn(input) | |
| return output | |
| } catch (stepError) { | |
| console.debug(`Workflow Step #${fnIndex + 1}, function: '${fn.name}'`, { | |
| input, | |
| output, | |
| error: stepError | |
| }) | |
| error = stepError | |
| /** | |
| * Abort workflow by removing all remaining functions. | |
| */ | |
| fnList.splice(1) | |
| } | |
| }, initialInput) | |
| if (error) { | |
| throw error | |
| } else { | |
| return result | |
| } | |
| } | |
| } | |
| /** | |
| * Functions defined for demonstration purposes. | |
| */ | |
| function addOne(x) { | |
| return x + 1 | |
| } | |
| function double(x) { | |
| return x * 2 | |
| } | |
| function square(x) { | |
| return x * x | |
| } | |
| async function wait(seconds) { | |
| await new Promise((resolve, reject) => { | |
| const milliseconds = seconds * 1000 | |
| if (milliseconds > 5000) { | |
| throw new Error(`Input value should not exceed 5 cause nobody got time for that.`) | |
| } | |
| setTimeout(() => { | |
| console.log('waiting ' + milliseconds + ' milliseconds') | |
| resolve() | |
| }, milliseconds) | |
| }) | |
| return seconds | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment