/** @test */
 public function shouldSupportVeryDeepNestedPromises()
 {
     $deferreds = [];
     // @TODO Increase count once global-queue is merged
     for ($i = 0; $i < 10; $i++) {
         $deferreds[] = $d = new Deferred();
         $p = $d->promise();
         $last = $p;
         for ($j = 0; $j < 10; $j++) {
             $last = $last->then(function ($result) {
                 return $result;
             });
         }
     }
     $p = null;
     foreach ($deferreds as $d) {
         if ($p) {
             $d->resolve($p);
         }
         $p = $d->promise();
     }
     $deferreds[0]->resolve(true);
     $mock = $this->createCallableMock();
     $mock->expects($this->once())->method('__invoke')->with($this->identicalTo(true));
     $deferreds[0]->promise()->then($mock);
 }
Example #2
0
 /** @test */
 public function shouldForwardValueWhenCallbackIsNull()
 {
     $mock = $this->createCallableMock();
     $mock->expects($this->once())->method('__invoke')->with($this->identicalTo(1));
     $d = new Deferred();
     $d->then(null, $this->expectCallableNever())->then($mock, $this->expectCallableNever());
     $d->resolve(1);
 }
Example #3
0
 /** @test */
 public function shouldPreserveTheOrderOfArrayWhenResolvingAsyncPromises()
 {
     $mock = $this->createCallableMock();
     $mock->expects($this->once())->method('__invoke')->with($this->identicalTo([1, 2, 3]));
     $deferred = new Deferred();
     all([resolve(1), $deferred->promise(), resolve(3)])->then($mock);
     $deferred->resolve(2);
 }
Example #4
0
 /** @test */
 public function shouldRejectARejectedPromise()
 {
     $expected = 123;
     $d = new Deferred();
     $d->reject($expected);
     $mock = $this->createCallableMock();
     $mock->expects($this->once())->method('__invoke')->with($this->identicalTo($expected));
     When::reject($d->promise())->then($this->expectCallableNever(), $mock);
 }
Example #5
0
 /** @test */
 public function shouldNotRelyOnArryIndexesWhenUnwrappingToASingleResolutionValue()
 {
     $mock = $this->createCallableMock();
     $mock->expects($this->once())->method('__invoke')->with($this->identicalTo(2));
     $d1 = new Deferred();
     $d2 = new Deferred();
     When::any(array('abc' => $d1->promise(), 1 => $d2->promise()), $mock);
     $d2->resolve(2);
     $d1->resolve(1);
 }
Example #6
0
 /** @test */
 public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseRejects()
 {
     $mock = $this->createCallableMock();
     $mock->expects($this->never())->method('__invoke');
     $deferred = new Deferred($mock);
     $deferred->reject();
     $mock2 = $this->getMockBuilder('React\\Promise\\CancellablePromiseInterface')->getMock();
     $mock2->expects($this->never())->method('cancel');
     race([$deferred->promise(), $mock2])->cancel();
 }
Example #7
0
 public function getPromiseTestAdapter()
 {
     $d = new Deferred();
     $factory = function () use($d) {
         return $d->promise();
     };
     return ['promise' => function () use($factory) {
         return new LazyPromise($factory);
     }, 'resolve' => [$d, 'resolve'], 'reject' => [$d, 'reject'], 'progress' => [$d, 'progress']];
 }
 /**
  * @test
  * @dataProvider invalidCallbackDataProvider
  **/
 public function shouldIgnoreNonFunctionsAndTriggerPhpNotice($var)
 {
     $errorCollector = new ErrorCollector();
     $errorCollector->register();
     $mock = $this->createCallableMock();
     $mock->expects($this->once())->method('__invoke')->with($this->identicalTo(1));
     $d = new Deferred();
     $d->then(null, $var)->then($this->expectCallableNever(), $mock);
     $d->reject(1);
     $errorCollector->assertCollectedError('Invalid $errorHandler argument passed to then(), must be null or callable.', E_USER_NOTICE);
     $errorCollector->unregister();
 }
Example #9
0
 /** @test */
 public function shouldRejectIfFirstSettledPromiseRejects()
 {
     $mock = $this->createCallableMock();
     $mock->expects($this->once())->method('__invoke')->with($this->identicalTo(2));
     $d1 = new Deferred();
     $d2 = new Deferred();
     $d3 = new Deferred();
     race([$d1->promise(), $d2->promise(), $d3->promise()])->then($this->expectCallableNever(), $mock);
     $d2->reject(2);
     $d1->resolve(1);
     $d3->resolve(3);
 }
Example #10
0
 /**
  * Create a new generator invoker
  * @param Client $client
  */
 function __construct(Client $client)
 {
     $this->client = $client;
     parent::__construct(function ($resolve, $reject) {
         return $this->cancel($resolve, $reject);
     });
 }
Example #11
0
 /** @test */
 public function shouldSupportDeepNestingInPromiseChains()
 {
     $d = new Deferred();
     $d->resolve(false);
     $result = When::resolve(When::resolve($d->then(function ($val) {
         $d = new Deferred();
         $d->resolve($val);
         $identity = function ($val) {
             return $val;
         };
         return When::resolve($d->then($identity))->then(function ($val) {
             return !$val;
         });
     })));
     $mock = $this->createCallableMock();
     $mock->expects($this->once())->method('__invoke')->with($this->identicalTo(true));
     $result->then($mock);
 }
Example #12
0
 /**
  * Emits a value from the observable. The returned promise is resolved with the emitted value once all subscribers
  * have been invoked.
  *
  * @param mixed $value
  *
  * @return \Interop\Async\Promise
  *
  * @throws \Error If the observable has resolved.
  */
 private function emit($value) : Promise
 {
     if ($this->resolved) {
         throw new \Error("The observable has been resolved; cannot emit more values");
     }
     if ($value instanceof Promise) {
         $deferred = new Deferred();
         $value->when(function ($e, $v) use($deferred) {
             if ($this->resolved) {
                 $deferred->fail(new \Error("The observable was resolved before the promise result could be emitted"));
                 return;
             }
             if ($e) {
                 $this->fail($e);
                 $deferred->fail($e);
                 return;
             }
             $deferred->resolve($this->emit($v));
         });
         return $deferred->promise();
     }
     $promises = [];
     foreach ($this->subscribers as $onNext) {
         try {
             $result = $onNext($value);
             if ($result instanceof Promise) {
                 $promises[] = $result;
             }
         } catch (\Throwable $e) {
             Loop::defer(static function () use($e) {
                 throw $e;
             });
         }
     }
     if (!$promises) {
         return new Success($value);
     }
     $deferred = new Deferred();
     $count = \count($promises);
     $f = static function ($e) use($deferred, $value, &$count) {
         if ($e) {
             Loop::defer(static function () use($e) {
                 throw $e;
             });
         }
         if (!--$count) {
             $deferred->resolve($value);
         }
     };
     foreach ($promises as $promise) {
         $promise->when($f);
     }
     return $deferred->promise();
 }
Example #13
0
 /**
  * @param \Amp\Observable $observable
  */
 public function __construct(Observable $observable)
 {
     $this->observable = $observable;
     $deferred =& $this->deferred;
     $values =& $this->values;
     $deferreds =& $this->deferreds;
     $resolved =& $this->resolved;
     $this->observable->subscribe(static function ($value) use(&$deferred, &$values, &$deferreds, &$resolved) {
         $values[] = $value;
         $deferreds[] = $pressure = new Deferred();
         if ($deferred !== null) {
             $temp = $deferred;
             $deferred = null;
             $temp->resolve(true);
         }
         if ($resolved) {
             return null;
         }
         return $pressure->promise();
     });
     $result =& $this->result;
     $error =& $this->exception;
     $this->observable->when(static function ($exception, $value) use(&$deferred, &$result, &$error, &$resolved) {
         $resolved = true;
         if ($exception) {
             $result = null;
             $error = $exception;
             if ($deferred !== null) {
                 $deferred->fail($exception);
             }
             return;
         }
         $result = $value;
         if ($deferred !== null) {
             $deferred->resolve(false);
         }
     });
 }
Example #14
0
 private function onParsedEntityHeaders(Client $client, array $parseResult)
 {
     $ireq = $this->initializeRequest($client, $parseResult);
     $id = $parseResult["id"];
     $client->bodyPromisors[$id] = $bodyPromisor = new Deferred();
     $ireq->body = new Body($bodyPromisor->promise());
     $this->clearKeepAliveTimeout($client);
     $this->respond($ireq);
 }
Example #15
0
 /**
  * Get the message content as it becomes available.
  *
  * @see IncomingMessage::content() to get the content as a string.
  *
  * @see IncomingMessage::contentStream() to read the content from a stream.
  *
  * The returned promise is notified when content arrives.
  * @see https://github.com/reactphp/promise#extendedpromiseinterfaceprogress
  *
  * Cancelling the returned promise discards any remaining content.
  *
  * @return null           [via promise] All content has been received.
  * @throws LogicException [via promise] The message content has already been consumed or discarded.
  */
 public function contentUnbuffered()
 {
     if ($this->contentHandled) {
         return reject(new LogicException('The message content has already been consumed or discarded.'));
     }
     $this->contentHandled = true;
     if (0 === $this->headerFrame->contentLength) {
         return resolve();
     }
     $deferred = new Deferred($this->cancelContentListener);
     $this->onBodyFrame = function ($exception, $frame, $final) use($deferred) {
         if ($exception) {
             $deferred->reject($exception);
         } else {
             $deferred->notify($frame->content);
             if ($final) {
                 $deferred->resolve();
             }
         }
     };
     return $deferred->promise();
 }
Example #16
0
 /** @test */
 public function shouldAllowRejectAfterProgress()
 {
     $d = new Deferred();
     $mock = $this->createCallableMock();
     $mock->expects($this->at(0))->method('__invoke')->with($this->identicalTo(1));
     $mock->expects($this->at(1))->method('__invoke')->with($this->identicalTo(2));
     $d->promise()->then($this->expectCallableNever(), $mock, $mock);
     $d->resolver()->progress(1);
     $d->resolver()->reject(2);
 }
Example #17
0
/**
 * Returns a promise that succeeds or fails when the first promise succeeds or fails.
 *
 * @param Promise[] $promises
 *
 * @return \Interop\Async\Promise
 *
 * @throws \Error If the array is empty or a non-Promise is in the array.
 */
function choose(array $promises) : Promise
{
    if (empty($promises)) {
        throw new \Error("No promises provided");
    }
    $deferred = new Deferred();
    $resolved = false;
    foreach ($promises as $promise) {
        if (!$promise instanceof Promise) {
            throw new \Error("Non-promise provided");
        }
        $promise->when(function ($exception, $value) use(&$resolved, $deferred) {
            if ($resolved) {
                return;
            }
            $resolved = true;
            if ($exception) {
                $deferred->fail($exception);
                return;
            }
            $deferred->resolve($value);
        });
    }
    return $deferred->promise();
}
Example #18
0
 /**
  * Declare this exchange.
  *
  * @recoil-coroutine
  *
  * @param boolean      $passive True to use a "passive" declare mode.
  * @param Channel|null $channel The application-managed channel to use (null = auto-managed).
  *
  * @throws ResourceNotFoundException The exchange does not exist.
  * @throws DeclareException          The exchange already exists with different a type or options.
  * @throws DeclareException          A reserved exchange name was used.
  * @throws ConnectionException       The connection is closed.
  * @throws ChannelException          The channel is closed.
  */
 private function declareExchange($passive, Channel $channel = null) : Generator
 {
     if ('amq.' === substr($this->name, 0, 4)) {
         return reject(DeclareException::exchangeNameIsReserved($this->name));
     }
     $deferred = new Deferred();
     $this->broker->acquireChannel(function ($exception, $brokerChannel) use($channel, $passive, $deferred) {
         if ($exception) {
             $deferred->reject($exception);
         } else {
             $brokerChannel->call(ExchangeDeclareFrame::create($this->name, $this->type->value(), $passive, $this->options->durable, $this->options->autoDelete, $this->options->internal, false, $this->arguments), ExchangeDeclareOkFrame::METHOD_ID, function ($exception, $frame) use($brokerChannel, $channel, $deferred) {
                 if (!$channel) {
                     $this->broker->releaseChannel($brokerChannel);
                 }
                 if ($exception) {
                     if ($exception instanceof AmqpException) {
                         if ($exception->getCode() === Constants::PRECONDITION_FAILED) {
                             $exception = DeclareException::exchangeTypeOrOptionMismatch($this->name, $this->type, $this->options, $exception);
                         } elseif ($exception->getCode() === Constants::NOT_FOUND) {
                             $exception = ResourceNotFoundException::exchangeNotFound($this->name, $exception);
                         }
                     }
                     $deferred->reject($exception);
                 } else {
                     $deferred->resolve($this);
                 }
             });
         }
     }, $channel);
     return $deferred->promise();
 }
Example #19
0
 public static function map($promisesOrValues, $mapFunc)
 {
     return When::resolve($promisesOrValues)->then(function ($array) use($mapFunc) {
         if (!is_array($array)) {
             $array = array();
         }
         $toResolve = count($array);
         $results = array();
         $deferred = new Deferred();
         if (!$toResolve) {
             $deferred->resolve($results);
         } else {
             $resolve = function ($item, $i) use($mapFunc, &$results, &$toResolve, $deferred) {
                 When::resolve($item)->then($mapFunc)->then(function ($mapped) use(&$results, $i, &$toResolve, $deferred) {
                     $results[$i] = $mapped;
                     if (0 === --$toResolve) {
                         $deferred->resolve($results);
                     }
                 }, array($deferred, 'reject'));
             };
             foreach ($array as $i => $item) {
                 $resolve($item, $i);
             }
         }
         return $deferred->promise();
     });
 }
Example #20
0
/**
 * Create an artificial timeout for any Promise instance
 *
 * If the timeout expires prior to promise resolution the returned
 * promise is failed.
 *
 * @param \Amp\Promise $promise The promise to which the timeout applies
 * @param int $msTimeout The timeout in milliseconds
 * @return \Amp\Promise
 */
function timeout(Promise $promise, $msTimeout)
{
    $resolved = false;
    $promisor = new Deferred();
    $watcherId = once(function () use($promisor, &$resolved) {
        $resolved = true;
        $promisor->fail(new TimeoutException("Promise resolution timed out"));
    }, $msTimeout);
    $promise->when(function ($error = null, $result = null) use($promisor, $watcherId, &$resolved) {
        if ($resolved) {
            return;
        }
        $resolved = true;
        cancel($watcherId);
        if ($error) {
            $promisor->fail($error);
        } else {
            $promisor->succeed($result);
        }
    });
    return $promisor->promise();
}
Example #21
0
 /** @test */
 public function shouldCancelOtherPendingInputArrayPromisesIfOnePromiseFulfills()
 {
     $mock = $this->createCallableMock();
     $mock->expects($this->never())->method('__invoke');
     $deferred = new Deferred($mock);
     $deferred->resolve();
     $mock2 = $this->getMock('React\\Promise\\CancellablePromiseInterface');
     $mock2->expects($this->once())->method('cancel');
     some([$deferred->promise(), $mock2], 1)->cancel();
 }
 /** @test */
 public function shouldProvideCorrectBasisValue()
 {
     $insertIntoArray = function ($arr, $val, $i) {
         $arr[$i] = $val;
         return $arr;
     };
     $d1 = new Deferred();
     $d2 = new Deferred();
     $d3 = new Deferred();
     $mock = $this->createCallableMock();
     $mock->expects($this->once())->method('__invoke')->with($this->identicalTo([1, 2, 3]));
     reduce([$d1->promise(), $d2->promise(), $d3->promise()], $insertIntoArray, [])->then($mock);
     $d3->resolve(3);
     $d1->resolve(1);
     $d2->resolve(2);
 }
Example #23
0
 /** @test */
 public function shouldReturnSilentlyOnProgressWhenAlreadyRejected()
 {
     $d = new Deferred();
     $d->reject(1);
     $this->assertNull($d->progress());
 }