/**
  *
  */
 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);
 }