Creates a promise that uses the builder-pattern. The chained functions will run asynchronously.
npm i build-a-promise
| pnpm add build-a-promise
Try it out in TypeScript Playground
import builder from 'build-a-promise'
const test = builder(r => (s: number, k: boolean) => {
console.log('Initial: ', {s,k})
// * Initial code (cannot be run asynchronously)
let i = 0
return {
__build() {
console.log('build')
return 'test-result' as const
},
async __init() {
// * Initial code (can be async)
console.log('__init')
},
__step() {
console.log('step')
},
i: (str: string) => {
console.log(i, str)
i++
}
}
})
async function testFunction() {
const returnedValue: 'test-result' = await test(2, true).i('test').i('asd').i('herpderp')
console.log({returnedValue})
}
testFunction()
/*
Console
-----------
Initial: {s: 2, k: true}
__init
0 'test'
step
1 'asd'
step
2 'herpderp'
step
build
{returnedValue: 'test-result'}
*/
The builder has two callbacks e.g.
const pizza = builder(r => () => {
// * Initial code
})
r
: If you want to resolve or reject the promise early, they're provided there.
const pizza = builder(({resolve, reject}) => () => {
// * Initial code
})
Next callback is the initial parameters provided the to function.
const pizza = builder(r => (pizzaType: string) => {
// * Initial code
})
...
await pizza('mexican')
Last thing you need to know, is that you return an object.
The object requires __build
, which will "build" the promise. The returned value of build
,
will define what type the promise returns.
const pizza = builder(r => (pizzaType: string) => {
// * Initial code
const extras = {
cheese = 0
}
return {
__build() {
return extras
},
extraCheese() {
extras.cheese++
}
}
})
...
const finishedPizza = await pizza('mexican').extraCheese().extraCheese()
// ^? finishedPizza = { cheese: number }
ANY function (both chained functions and builder options e.g. __
) may provide a returned value.
If a function returns a value - it will be equivilant to resolve(value)
.
The difference being, returning a value will also provide a type.
Exceptions:
- The returned value of
__catch
will be equivilant toreject(value)
__finally
cannot return anything
Note: If
__build
returns void, the returned type isPromise<undefined | Others>
- whereOthers
are the returned types from other functions.
You can also return a function, if you provide a third callback:
const pizza = builder(r => (pizzaType: string) => (...args) => {
...
})
pizza('mexican')(...args)
pizza('mexican').extraCheese().extraCheese()(...args)
Order of execution:
__init
→ (* → __step
)* → __build
→ __finally
Name | Description |
---|---|
__init?.() |
The initial function to be called. Used to initialize values that require asynchronous operatinos. Like the other declared functions here, it will be called without chaining it. |
__catch?.(error) |
The whole chain is inside a try-catch block. If an error occurs, and __catch is defined, rather than throwing the error, __catch will be called. Note: If __catch is not defined, reject(error), will be called before throwing an error. |
__step?.() |
Runs after each step in the chain functions. Good for things like validating every step. |
__build?.() |
Is called as a last function to be called (before finally). This returns the awaited result of the builder-pattern. It is optional - as sometimes we just want to run a chain of commands without a final "build". |
__finally?.() |
The last function - and will always run. Consider it as a way to clean-up after the full execution. |