public static function reduce($promisesOrValues, callable $reduceFunc, $initialValue = null)
{
$cancellationQueue = new CancellationQueue();
return new Promise(function ($resolve, $reject, $cancel) use($promisesOrValues, $reduceFunc, $initialValue, $cancellationQueue) {
self::doResolve($promisesOrValues)->done(function ($array) use($reduceFunc, $initialValue, $resolve, $reject, $cancel, $cancellationQueue) {
if (!is_array($array)) {
$array = [];
}
$total = count($array);
$i = 0;
// Wrap the supplied $reduceFunc with one that handles promises and then delegates to the supplied.
//
$wrappedReduceFunc = function (PromiseInterface $current, $val) use($reduceFunc, $cancellationQueue, $total, &$i) {
$cancellationQueue->enqueue($val);
return $current->then(function ($c) use($reduceFunc, $total, &$i, $val) {
return self::doResolve($val)->then(function ($value) use($reduceFunc, $total, &$i, $c) {
return $reduceFunc($c, $value, $i++, $total);
});
});
};
$initialValue = self::doResolve($initialValue);
$cancellationQueue->enqueue($initialValue);
array_reduce($array, $wrappedReduceFunc, $initialValue)->done($resolve, $reject, $cancel);
}, $reject, $cancel);
}, $cancellationQueue);
}