Skip to content

Instantly share code, notes, and snippets.

@kylehovey
Last active July 15, 2019 16:06
Show Gist options
  • Save kylehovey/17d818bd99a26399b0cd4bec39d135b9 to your computer and use it in GitHub Desktop.
Save kylehovey/17d818bd99a26399b0cd4bec39d135b9 to your computer and use it in GitHub Desktop.
Functional version of a promise that allows you to resolve it outside of the callback in the promise constructor
/**
* Creates an intermediate value that can be resolved later.
* @return {Object} Eventual
* @return {Function} Eventual.then Acts like Promise.then for the eventual value
* @return {Function} Eventual.resolve Acts like Promise.resolve for the eventual
* @return {Function} Eventual.reject Acts like Promise.reject for the eventual
*/
const eventual = () => (
_eventual => ({
/**
* Forward all arguments to the promise contained inside of eventual
* @param {Function(Function resolve, Function reject))}
* @return {Promise}
*/
then: (...args) => _eventual.then(({ promise }) => promise.then(...args)),
/**
* Resolve the promise once the call stack is empty
* @param {Value} val Value to resolve to
*/
resolve: val => {
_eventual.then(({ resolve }) => resolve(val));
},
/**
* Reject the promise once the call stack is empty
* @param {Value} val Value to reject with
*/
reject: val => {
_eventual.then(({ reject }) => reject(val));
},
})
)(
/*
* Outer promise is only here to resolve the methods
* in the inner promise callback
*/
new Promise(handler => {
/*
* The `setTimeout(..., 0)` is so that the inner promise
* calls the outer resolver only once the call stack
* is empty and `promise` has been assigned the rvalue
* returned by the inner promise's constructor.
*/
const promise = new Promise((resolve, reject) => {
setTimeout(
() => handler({ promise, resolve, reject }),
0,
);
});
})
);
/**
* Creation is easy enough
*/
const thing = eventual();
/**
* We can safely assume that the value is ready when cubed
*/
thing.then(x => x ** 2).then(console.log);
thing.then(x => x ** 3).then(console.log);
thing.then(x => x ** 4).then(console.log);
/**
* Some undetermined amount of time later
*/
thing.resolve(3);
/**
* Console output:
* 9
* 27
* 81
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment