Skip to content

Instantly share code, notes, and snippets.

@trozdol
Last active July 6, 2023 20:12
Show Gist options
  • Select an option

  • Save trozdol/729a3e7b39f5c2e42b57967e89d12912 to your computer and use it in GitHub Desktop.

Select an option

Save trozdol/729a3e7b39f5c2e42b57967e89d12912 to your computer and use it in GitHub Desktop.
/**
* 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