Skip to content

Instantly share code, notes, and snippets.

@cmdruid
Last active December 30, 2022 00:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cmdruid/eaaa134293380c46f106cd1b6fe02f5b to your computer and use it in GitHub Desktop.
Save cmdruid/eaaa134293380c46f106cd1b6fe02f5b to your computer and use it in GitHub Desktop.
ES6 Asynchronous Pipe Function, in Typescript
// Useful for type-checking your pipe middleware.
export type PipeMethod<T> = (input : T) => Promise<T>
// Return type for the pipe method.
type PipeReturn<T> = (input: T, catcher: Function) => Promise<PipeOutput<T>>
// Object returned by the pipe method.
interface PipeOutput<T> {
errors: unknown[];
output: T
ok : boolean
}
export function pipe<T>(
// First curry input is array of middleware.
...fns : PipeMethod<T>[]
) : PipeReturn<T> {
// Second curry input is the initial value.
// You can also provide a custom error handler.
return async (
input : T,
catcher? : Function
) => {
// Initialize our variables.
let errors = [], output = input
// Simple loop, no silly array reducers.
for (const fn of fns) {
try {
// Elegant async / await.
output = await fn(output)
} catch(err) {
// Our catch logic.
if (catcher) catcher(err, output)
errors.push(err)
}
}
// We return a helpful object with boolean and errors.
return { errors, output, ok: errors.length === 0 }
}
}
/** EXAMPLE USAGE **/
import { pipe, PipeMethod } from './pipe.js'
// Handy delay method for async / await testing.
const delay = (ms : number = 500) : Promise<void> => new Promise((res) => setTimeout(() => res(), ms))
async function waitThenAddThree(num : number) : Promise<number> {
await delay()
return num + 3
}
async function waitThenMulTwo(num : number) : Promise<number> {
await delay()
return num * 2
}
async function waitThenThrow(num : number) : Promise<number> {
await delay()
if (num > 0) throw 'kaboom!'
return num
}
function catcher(err : unknown, data : any) {
/** Example custom error handler. */
console.log(err, data)
// You can also rethrow to kill the pipe early.
throw 'another boom!'
}
// By declaring a type (e.x number) on the PipeMethod,
// the whole pipeline will guard for that type.
const middlewares : PipeMethod<number>[] = [
waitThenAddThree,
waitThenThrow,
waitThenMulTwo
]
// Example usage of pipe method.
const output = await pipe(...middlewares)(5, catcher)
console.log(output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment