public static function some($promisesOrValues, $howMany)
{
$cancellationQueue = new CancellationQueue();
return new Promise(function ($resolve, $reject, $cancel) use($promisesOrValues, $howMany, $cancellationQueue) {
self::doResolve($promisesOrValues)->done(function ($array) use($resolve, $reject, $cancel, $howMany, $cancellationQueue) {
if (!is_array($array) || $howMany < 1) {
$resolve([]);
return;
}
$len = count($array);
if ($len < $howMany) {
throw new UnderflowException(sprintf('Input array must contain at least %d items but contains only %s items.', $howMany, $len));
}
$toResolve = $howMany;
$toReject = $len - $toResolve + 1;
$values = [];
$reasons = [];
foreach ($array as $i => $promiseOrValue) {
$fulfiller = function ($val) use($i, &$values, &$toResolve, $toReject, $resolve, $cancellationQueue) {
if ($toResolve < 1 || $toReject < 1) {
return;
}
$values[$i] = $val;
if (0 === --$toResolve) {
$resolve($values);
$cancellationQueue();
}
};
$rejecter = function ($reason) use($i, &$reasons, &$toReject, $toResolve, $reject, $cancellationQueue) {
if ($toResolve < 1 || $toReject < 1) {
return;
}
$reasons[$i] = $reason;
if (0 === --$toReject) {
$reject($reasons);
$cancellationQueue();
}
};
$canceller = $cancel;
$cancellationQueue->enqueue($promiseOrValue);
self::doResolve($promiseOrValue)->done($fulfiller, $rejecter, $canceller);
}
}, $reject, $cancel);
}, $cancellationQueue);
}