Last active
April 19, 2025 14:30
-
-
Save NyanHelsing/798f6122ffb17ac0f763d63ca0b6708d to your computer and use it in GitHub Desktop.
WaitLift
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
/** | |
* curryFlip(fn) takes a two-argument function `fn` and returns | |
* a curried function that applies `fn` with its arguments reversed. | |
*/ | |
const curryFlip = (fn) => a => b => fn(b, a); | |
/** | |
* Returns an array of promises (or values) where each item | |
* is [key, await transform(value)]. | |
*/ | |
function createAsyncEntriesTransformer(asyncStrategy) { | |
return async function asyncEntriesTransformer(obj, transform) { | |
const entryTransform = async ([key, value]) => | |
[key, await transform(await value)]; | |
const entriesToTransform = Object.entries(obj); | |
const transformingEntries = entriesToTransform.map(entryTransform); | |
const strategyResolution = asyncStrategy(transformingEntries); | |
return Object.fromEntries(await strategyResolution); | |
}; | |
} | |
// Now we can reuse createTransformedPairs in allEntries and allEntriesSettled: | |
/** | |
* allEntries(iterable, transform): | |
* - transforms each value in parallel | |
* - rejects on the first failed transform | |
* - returns final object | |
*/ | |
const allEntries = createAsyncEntriesTransformer(_ => Promise.all(_)); | |
/** | |
* allEntriesSettled(iterable, transform): | |
* - transforms each value in parallel | |
* - never rejects, always resolves with final object | |
* - for each rejection, place the reason at that key | |
*/ | |
const allEntriesSettled = createAsyncEntriesTransformer(_ => Promise.allSettled(_)); | |
/** | |
* liftAllEntries(iterable, transform): | |
* Takes an async function and returns a function that | |
* can be applied to the values of an object, transforming | |
* each value in parallel. | |
*/ | |
export const liftPromiseAllEntries = curryFlip(allEntries); | |
/** | |
* liftAllEntriesSettled(iterable, transform): | |
* Takes an async function and returns a function that | |
* can be applied to an object, transforming each value in parallel, | |
* and returning a promise that resolves to an object with | |
* the same keys, where each value is the settlement of the | |
* corresponding promise. | |
*/ | |
export const liftPromiseAllEntriesSettled = curryFlip(allEntriesSettled); | |
// ---------------------------------------------------------------------------- | |
// I don't care I'm gonna do it anyway | |
Object.defineProperty(Promise, 'allEntries', { | |
value: function (iterable) { | |
return allEntries(iterable, (x) => x); // identity transform | |
}, | |
writable: true, | |
configurable: true | |
}); | |
Object.defineProperty(Promise, 'allEntriesSettled', { | |
value: function (iterable) { | |
return allEntriesSettled(iterable, (x) => x); // identity transform | |
}, | |
writable: true, | |
configurable: true | |
}); | |
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
const promiseValue = (value, time) => { | |
const { promise, resolve } = Promise.withResolvers(); | |
setTimeout(() => resolve(value), time) | |
return promise; | |
} | |
const { | |
myValue, | |
otherValue | |
} = liftPromiseAllEntries((resolved) => resolved * 2)({ | |
myValue: promiseValue(42, 100), | |
otherValue: promiseValue(666, 1000) | |
}) | |
console.log(myValue) // logs 84 | |
console.log(otherValue) // logs 1336 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment