/** * */ public function testApiInvoke_ThrowsExceptionsFromCancel() { $this->setExpectedException(Exception::class, 'test'); $mock = $this->getMock(PromiseInterface::class); $mock->expects($this->once())->method('cancel')->will($this->throwException(new Exception('test'))); $cancellationQueue = new CancellationQueue(); $cancellationQueue->enqueue($mock); $cancellationQueue(); }
/** * Reduce Promises and/or values using $reduceFunc with $initialValue being Promise or primitive value. * * @see array_reduce * * @param PromiseInterface[]|mixed[] $promisesOrValues * @param callable $reduceFunc * @param PromiseInterface|mixed|null $initialValue * @return PromiseInterface * @resolves mixed * @rejects Error|Exception|string|null * @cancels Error|Exception|string|null */ 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); }