diff --git a/CHANGELOG.md b/CHANGELOG.md index c722a12..e9e7047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Add some devtools functions for custom inspect formatting * Add `Pledge#getResolvedFunction()` method, which can be passed as an old-style callback * Fix some `Swift` methods not using the correct schedulers +* Implement a custom `done` and `waterfall` static method for the `SwiftPledge` class ## 0.9.2 (2024-02-25) diff --git a/lib/pledge.js b/lib/pledge.js index 8b4b268..584496b 100644 --- a/lib/pledge.js +++ b/lib/pledge.js @@ -1382,13 +1382,15 @@ var Timeout = Fn.inherits('Pledge', function TimeoutPledge(executor, timeout, me * * @author Jelle De Loecker * @since 0.8.15 - * @version 0.8.15 + * @version 0.9.3 * * @param {Function} executor */ const Swift = Fn.inherits(Pledge, function SwiftPledge(executor) { - this[EXECUTOR] = executor; - this[START_EXECUTOR](false); + if (executor != null) { + this[EXECUTOR] = executor; + this[START_EXECUTOR](false); + } }); const SwiftObject = Object.create(Bound.Function); @@ -1396,6 +1398,33 @@ SwiftObject[Blast.flowPledgeClass] = Swift; SwiftObject[Blast.asyncScheduler] = Blast.callNow; Swift[FNC] = SwiftObject; +/** + * Handle an old-style callback for a pledge or promise + * + * @author Jelle De Loecker + * @since 0.9.3 + * @version 0.9.3 + */ +Swift.setStatic(function done(value, callback) { + + // Pass through falsy or non-object values + if (!value || typeof value != 'object') { + return callback(null, value); + } + + // Pass non-thenables through + if (!value.then) { + return callback(null, value); + } + + // See if we can rip the values out of Pledge instances + if (value[STATE] == RESOLVED) { + return callback(null, value[RESOLVED_VALUE]); + } + + value.then(val => callback(null, val), callback); +}); + /** * Do the given tasks in parallel * @@ -1502,18 +1531,61 @@ Swift.setStatic(function execute(value) { return value; }); +/** + * Do a single waterfall task + * + * @author Jelle De Loecker + * @since 0.9.3 + * @version 0.9.3 + */ +const doWaterfallTask = (pledge, tasks, index, max_index, previous_value) => { + + let task = tasks[index], + next_value; + + if (typeof task == 'function') { + try { + next_value = task(previous_value); + } catch (err) { + return pledge.reject(err); + } + } else { + next_value = task; + } + + Swift.done(next_value, (err, result) => { + + if (err) { + return pledge.reject(err); + } + + if (index == max_index) { + return pledge.resolve(result); + } + + doWaterfallTask(pledge, tasks, index + 1, max_index, result); + }); +}; + /** * Perform a swift waterfall * * @author Jelle De Loecker * @since 0.8.15 - * @version 0.8.15 + * @version 0.9.3 * * @return {SwiftPledge|Mixed} */ Swift.setStatic(function waterfall(...tasks) { - let result = SwiftObject.waterfall(...tasks); - return Swift.execute(result); + let pledge = new Swift(); + + doWaterfallTask(pledge, tasks, 0, tasks.length - 1, null); + + if (pledge[STATE] == RESOLVED) { + return pledge[RESOLVED_VALUE]; + } + + return pledge; }); /**