Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ $result = Block\await($promise, $loop);
Once the promise is resolved, this will return whatever the promise resolves to.

Once the promise is rejected, this will throw whatever the promise rejected with.
If the promise did not reject with an `Exception`, then this function will
throw an `UnexpectedValueException` instead.

```php
try {
Expand Down Expand Up @@ -185,6 +187,8 @@ be used to correlate the return array to the promises passed.

If ANY promise fails to resolve, this will try to `cancel()` all
remaining promises and throw an `Exception`.
If the promise did not reject with an `Exception`, then this function will
throw an `UnexpectedValueException` instead.

If no $timeout is given and either promise stays pending, then this will
potentially wait/block forever until the last promise is settled.
Expand Down
18 changes: 16 additions & 2 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ function sleep($time, LoopInterface $loop)
* Once the promise is resolved, this will return whatever the promise resolves to.
*
* Once the promise is rejected, this will throw whatever the promise rejected with.
* If the promise did not reject with an `Exception`, then this function will
* throw an `UnexpectedValueException` instead.
*
* If no $timeout is given and the promise stays pending, then this will
* potentially wait/block forever until the promise is settled.
Expand All @@ -47,6 +49,7 @@ function await(PromiseInterface $promise, LoopInterface $loop, $timeout = null)
$wait = true;
$resolved = null;
$exception = null;
$rejected = false;

if ($timeout !== null) {
$promise = Timer\timeout($promise, $timeout, $loop);
Expand All @@ -58,8 +61,9 @@ function ($c) use (&$resolved, &$wait, $loop) {
$wait = false;
$loop->stop();
},
function ($error) use (&$exception, &$wait, $loop) {
function ($error) use (&$exception, &$rejected, &$wait, $loop) {
$exception = $error;
$rejected = true;
$wait = false;
$loop->stop();
}
Expand All @@ -69,7 +73,15 @@ function ($error) use (&$exception, &$wait, $loop) {
$loop->run();
}

if ($exception !== null) {
if ($rejected) {
if (!$exception instanceof \Exception) {
$exception = new \UnexpectedValueException(
'Promise rejected with unexpected value of type ' . (is_object(($exception) ? get_class($exception) : gettype($exception))),
0,
$exception instanceof \Throwable ? $exception : null
);
}

throw $exception;
}

Expand Down Expand Up @@ -139,6 +151,8 @@ function awaitAny(array $promises, LoopInterface $loop, $timeout = null)
*
* If ANY promise fails to resolve, this will try to cancel() all
* remaining promises and throw an Exception.
* If the promise did not reject with an `Exception`, then this function will
* throw an `UnexpectedValueException` instead.
*
* If no $timeout is given and either promise stays pending, then this will
* potentially wait/block forever until the last promise is settled.
Expand Down
11 changes: 11 additions & 0 deletions tests/FunctionAwaitAllTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ public function testAwaitAllRejected()
Block\awaitAll($all, $this->loop);
}

public function testAwaitAllRejectedWithFalseWillWrapInUnexpectedValueException()
{
$all = array(
$this->createPromiseResolved(1),
Promise\reject(false)
);

$this->setExpectedException('UnexpectedValueException');
Block\awaitAll($all, $this->loop);
}

public function testAwaitAllOnlyRejected()
{
$all = array(
Expand Down
32 changes: 32 additions & 0 deletions tests/FunctionAwaitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,38 @@ public function testAwaitOneRejected()
Block\await($promise, $this->loop);
}

public function testAwaitOneRejectedWithFalseWillWrapInUnexpectedValueException()
{
$promise = Promise\reject(false);

$this->setExpectedException('UnexpectedValueException');
Block\await($promise, $this->loop);
}

public function testAwaitOneRejectedWithNullWillWrapInUnexpectedValueException()
{
$promise = Promise\reject(null);

$this->setExpectedException('UnexpectedValueException');
Block\await($promise, $this->loop);
}

/**
* @requires PHP 7
*/
public function testAwaitOneRejectedWithPhp7ErrorWillWrapInUnexpectedValueExceptionWithPrevious()
{
$promise = Promise\reject(new Error('Test'));

try {
Block\await($promise, $this->loop);
$this->fail();
} catch (UnexpectedValueException $e) {
$this->assertInstanceOf('Throwable', $e->getPrevious());
$this->assertEquals('Test', $e->getPrevious()->getMessage());
}
}

public function testAwaitOneResolved()
{
$promise = $this->createPromiseResolved(2);
Expand Down