mirror of
https://github.com/retailcrm/graphql-php.git
synced 2025-02-14 11:33:13 +03:00
Execution: added SyncPromiseAdapter and made it default for Executor (+removed GenericPromiseAdapter)
This commit is contained in:
parent
48d78412ec
commit
e97ca7f971
53
src/Deferred.php
Normal file
53
src/Deferred.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
namespace GraphQL;
|
||||||
|
|
||||||
|
use GraphQL\Executor\Promise\Adapter\SyncPromise;
|
||||||
|
|
||||||
|
class Deferred
|
||||||
|
{
|
||||||
|
private static $queue;
|
||||||
|
|
||||||
|
private $callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var SyncPromise
|
||||||
|
*/
|
||||||
|
public $promise;
|
||||||
|
|
||||||
|
public static function getQueue()
|
||||||
|
{
|
||||||
|
return self::$queue ?: self::$queue = new \SplQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function runQueue()
|
||||||
|
{
|
||||||
|
$q = self::getQueue();
|
||||||
|
while (!$q->isEmpty()) {
|
||||||
|
/** @var self $dfd */
|
||||||
|
$dfd = $q->dequeue();
|
||||||
|
$dfd->run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct(callable $callback)
|
||||||
|
{
|
||||||
|
$this->callback = $callback;
|
||||||
|
$this->promise = new SyncPromise();
|
||||||
|
self::getQueue()->enqueue($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function then($onFulfilled = null, $onRejected = null)
|
||||||
|
{
|
||||||
|
return $this->promise->then($onFulfilled, $onRejected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function run()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$cb = $this->callback;
|
||||||
|
$this->promise->resolve($cb());
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->promise->reject($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ namespace GraphQL\Executor;
|
|||||||
|
|
||||||
use GraphQL\Error\Error;
|
use GraphQL\Error\Error;
|
||||||
use GraphQL\Error\InvariantViolation;
|
use GraphQL\Error\InvariantViolation;
|
||||||
|
use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
|
||||||
use GraphQL\Executor\Promise\Promise;
|
use GraphQL\Executor\Promise\Promise;
|
||||||
use GraphQL\Language\AST\DocumentNode;
|
use GraphQL\Language\AST\DocumentNode;
|
||||||
use GraphQL\Language\AST\FieldNode;
|
use GraphQL\Language\AST\FieldNode;
|
||||||
@ -10,7 +11,6 @@ use GraphQL\Language\AST\FragmentDefinitionNode;
|
|||||||
use GraphQL\Language\AST\NodeKind;
|
use GraphQL\Language\AST\NodeKind;
|
||||||
use GraphQL\Language\AST\OperationDefinitionNode;
|
use GraphQL\Language\AST\OperationDefinitionNode;
|
||||||
use GraphQL\Language\AST\SelectionSetNode;
|
use GraphQL\Language\AST\SelectionSetNode;
|
||||||
use GraphQL\Executor\Promise\Adapter\GenericPromiseAdapter;
|
|
||||||
use GraphQL\Executor\Promise\PromiseAdapter;
|
use GraphQL\Executor\Promise\PromiseAdapter;
|
||||||
use GraphQL\Schema;
|
use GraphQL\Schema;
|
||||||
use GraphQL\Type\Definition\AbstractType;
|
use GraphQL\Type\Definition\AbstractType;
|
||||||
@ -68,7 +68,7 @@ class Executor
|
|||||||
*/
|
*/
|
||||||
public static function getPromiseAdapter()
|
public static function getPromiseAdapter()
|
||||||
{
|
{
|
||||||
return self::$promiseAdapter ?: (self::$promiseAdapter = new GenericPromiseAdapter());
|
return self::$promiseAdapter ?: (self::$promiseAdapter = new SyncPromiseAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,6 +112,10 @@ class Executor
|
|||||||
$executor = new self($exeContext, $promiseAdapter);
|
$executor = new self($exeContext, $promiseAdapter);
|
||||||
$result = $executor->executeQuery();
|
$result = $executor->executeQuery();
|
||||||
|
|
||||||
|
if ($result instanceof Promise && $promiseAdapter instanceof SyncPromiseAdapter) {
|
||||||
|
$result = $promiseAdapter->wait($result);
|
||||||
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace GraphQL\Executor\Promise\Adapter;
|
|
||||||
|
|
||||||
use GraphQL\Executor\Promise\PromiseAdapter;
|
|
||||||
|
|
||||||
class GenericPromiseAdapter implements PromiseAdapter
|
|
||||||
{
|
|
||||||
public function isPromise($value)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accepts value qualified by `isPromise` and returns other promise.
|
|
||||||
*
|
|
||||||
* @param $promise
|
|
||||||
* @param callable|null $onFullFilled
|
|
||||||
* @param callable|null $onRejected
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function then($promise, callable $onFullFilled = null, callable $onRejected = null)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (null !== $onFullFilled) {
|
|
||||||
$promise = $onFullFilled($promise);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->createResolvedPromise($promise);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
if (null !== $onRejected) {
|
|
||||||
$onRejected($e);
|
|
||||||
}
|
|
||||||
return $this->createRejectedPromise($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createPromise(callable $resolver)
|
|
||||||
{
|
|
||||||
return $resolver(function ($value) {
|
|
||||||
return $value;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createResolvedPromise($promiseOrValue = null)
|
|
||||||
{
|
|
||||||
return $promiseOrValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createRejectedPromise($reason)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createPromiseAll($promisesOrValues)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,10 +22,16 @@ class SyncPromise
|
|||||||
*/
|
*/
|
||||||
public static $queue;
|
public static $queue;
|
||||||
|
|
||||||
|
public static function getQueue()
|
||||||
|
{
|
||||||
|
return self::$queue ?: self::$queue = new \SplQueue();
|
||||||
|
}
|
||||||
|
|
||||||
public static function runQueue()
|
public static function runQueue()
|
||||||
{
|
{
|
||||||
while (self::$queue && !self::$queue->isEmpty()) {
|
$q = self::getQueue();
|
||||||
$task = self::$queue->dequeue();
|
while (!$q->isEmpty()) {
|
||||||
|
$task = $q->dequeue();
|
||||||
$task();
|
$task();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,13 +46,6 @@ class SyncPromise
|
|||||||
*/
|
*/
|
||||||
private $waiting = [];
|
private $waiting = [];
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
if (!self::$queue) {
|
|
||||||
self::$queue = new \SplQueue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function reject(\Exception $reason)
|
public function reject(\Exception $reason)
|
||||||
{
|
{
|
||||||
switch ($this->state) {
|
switch ($this->state) {
|
||||||
@ -73,7 +72,7 @@ class SyncPromise
|
|||||||
if ($value === $this) {
|
if ($value === $this) {
|
||||||
throw new \Exception("Cannot resolve promise with self");
|
throw new \Exception("Cannot resolve promise with self");
|
||||||
}
|
}
|
||||||
if ($value instanceof self) {
|
if (is_object($value) && method_exists($value, 'then')) {
|
||||||
$value->then(
|
$value->then(
|
||||||
function($resolvedValue) {
|
function($resolvedValue) {
|
||||||
$this->resolve($resolvedValue);
|
$this->resolve($resolvedValue);
|
||||||
@ -123,7 +122,7 @@ class SyncPromise
|
|||||||
Utils::invariant($this->state !== self::PENDING, 'Cannot enqueue derived promises when parent is still pending');
|
Utils::invariant($this->state !== self::PENDING, 'Cannot enqueue derived promises when parent is still pending');
|
||||||
|
|
||||||
foreach ($this->waiting as $descriptor) {
|
foreach ($this->waiting as $descriptor) {
|
||||||
self::$queue->enqueue(function () use ($descriptor) {
|
self::getQueue()->enqueue(function () use ($descriptor) {
|
||||||
/** @var $promise self */
|
/** @var $promise self */
|
||||||
list($promise, $onFulfilled, $onRejected) = $descriptor;
|
list($promise, $onFulfilled, $onRejected) = $descriptor;
|
||||||
|
|
||||||
|
146
src/Executor/Promise/Adapter/SyncPromiseAdapter.php
Normal file
146
src/Executor/Promise/Adapter/SyncPromiseAdapter.php
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
<?php
|
||||||
|
namespace GraphQL\Executor\Promise\Adapter;
|
||||||
|
|
||||||
|
use GraphQL\Deferred;
|
||||||
|
use GraphQL\Error\InvariantViolation;
|
||||||
|
use GraphQL\Executor\Promise\Promise;
|
||||||
|
use GraphQL\Executor\Promise\PromiseAdapter;
|
||||||
|
use GraphQL\Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SyncPromiseAdapter
|
||||||
|
*
|
||||||
|
* Allows changing order of field resolution even in sync environments
|
||||||
|
* (by leveraging queue of deferreds and promises)
|
||||||
|
*
|
||||||
|
* @package GraphQL\Executor\Promise\Adapter
|
||||||
|
*/
|
||||||
|
class SyncPromiseAdapter implements PromiseAdapter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function isThenable($value)
|
||||||
|
{
|
||||||
|
return $value instanceof Deferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function convert($value)
|
||||||
|
{
|
||||||
|
if (!$value instanceof Deferred) {
|
||||||
|
throw new InvariantViolation('Expected instance of GraphQL\Deferred, got ' . Utils::printSafe($value));
|
||||||
|
}
|
||||||
|
return new Promise($value->promise, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function then(Promise $promise, callable $onFulfilled = null, callable $onRejected = null)
|
||||||
|
{
|
||||||
|
/** @var SyncPromise $promise */
|
||||||
|
$promise = $promise->adoptedPromise;
|
||||||
|
return new Promise($promise->then($onFulfilled, $onRejected), $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function createPromise(callable $resolver)
|
||||||
|
{
|
||||||
|
$promise = new SyncPromise();
|
||||||
|
|
||||||
|
$resolver(
|
||||||
|
[$promise, 'resolve'],
|
||||||
|
[$promise, 'reject']
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Promise($promise, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function createResolvedPromise($value = null)
|
||||||
|
{
|
||||||
|
$promise = new SyncPromise();
|
||||||
|
return new Promise($promise->resolve($value), $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function createRejectedPromise(\Exception $reason)
|
||||||
|
{
|
||||||
|
$promise = new SyncPromise();
|
||||||
|
return new Promise($promise->reject($reason), $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function createPromiseAll(array $promisesOrValues)
|
||||||
|
{
|
||||||
|
$all = new SyncPromise();
|
||||||
|
|
||||||
|
$total = count($promisesOrValues);
|
||||||
|
$count = 0;
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
foreach ($promisesOrValues as $index => $promiseOrValue) {
|
||||||
|
if ($promiseOrValue instanceof Promise) {
|
||||||
|
$promiseOrValue->then(
|
||||||
|
function($value) use ($index, &$count, $total, &$result, $all) {
|
||||||
|
$result[$index] = $value;
|
||||||
|
$count++;
|
||||||
|
if ($count >= $total) {
|
||||||
|
$all->resolve($result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[$all, 'reject']
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$result[$index] = $promiseOrValue;
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($count === $total) {
|
||||||
|
$all->resolve($result);
|
||||||
|
}
|
||||||
|
return new Promise($all, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function wait(Promise $promise)
|
||||||
|
{
|
||||||
|
$fulfilledValue = null;
|
||||||
|
$rejectedReason = null;
|
||||||
|
|
||||||
|
$promise->then(
|
||||||
|
function ($value) use (&$fulfilledValue) {
|
||||||
|
$fulfilledValue = $value;
|
||||||
|
},
|
||||||
|
function ($reason) use (&$rejectedReason) {
|
||||||
|
$rejectedReason = $reason;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
while (
|
||||||
|
$promise->adoptedPromise->state === SyncPromise::PENDING &&
|
||||||
|
!(Deferred::getQueue()->isEmpty() && SyncPromise::getQueue()->isEmpty())
|
||||||
|
) {
|
||||||
|
Deferred::runQueue();
|
||||||
|
SyncPromise::runQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($promise->adoptedPromise->state === SyncPromise::PENDING) {
|
||||||
|
throw new InvariantViolation("Could not resolve promise");
|
||||||
|
}
|
||||||
|
if ($rejectedReason instanceof \Exception) {
|
||||||
|
throw $rejectedReason;
|
||||||
|
}
|
||||||
|
return $fulfilledValue;
|
||||||
|
}
|
||||||
|
}
|
@ -242,6 +242,9 @@ class Utils
|
|||||||
if (is_object($var)) {
|
if (is_object($var)) {
|
||||||
return 'instance of ' . get_class($var);
|
return 'instance of ' . get_class($var);
|
||||||
}
|
}
|
||||||
|
if ('' === $var) {
|
||||||
|
return '(empty string)';
|
||||||
|
}
|
||||||
if (is_scalar($var)) {
|
if (is_scalar($var)) {
|
||||||
return (string) $var;
|
return (string) $var;
|
||||||
}
|
}
|
||||||
|
203
tests/Executor/Promise/SyncPromiseAdapterTest.php
Normal file
203
tests/Executor/Promise/SyncPromiseAdapterTest.php
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
<?php
|
||||||
|
namespace GraphQL\Tests\Executor\Promise;
|
||||||
|
|
||||||
|
use GraphQL\Deferred;
|
||||||
|
use GraphQL\Error\InvariantViolation;
|
||||||
|
use GraphQL\Executor\Promise\Adapter\SyncPromise;
|
||||||
|
use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
|
||||||
|
use GraphQL\Executor\Promise\Promise;
|
||||||
|
|
||||||
|
class SyncPromiseAdapterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var SyncPromiseAdapter
|
||||||
|
*/
|
||||||
|
private $promises;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->promises = new SyncPromiseAdapter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsThenable()
|
||||||
|
{
|
||||||
|
$this->assertEquals(true, $this->promises->isThenable(new Deferred(function() {})));
|
||||||
|
$this->assertEquals(false, $this->promises->isThenable(false));
|
||||||
|
$this->assertEquals(false, $this->promises->isThenable(true));
|
||||||
|
$this->assertEquals(false, $this->promises->isThenable(1));
|
||||||
|
$this->assertEquals(false, $this->promises->isThenable(0));
|
||||||
|
$this->assertEquals(false, $this->promises->isThenable('test'));
|
||||||
|
$this->assertEquals(false, $this->promises->isThenable(''));
|
||||||
|
$this->assertEquals(false, $this->promises->isThenable([]));
|
||||||
|
$this->assertEquals(false, $this->promises->isThenable(new \stdClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testConvert()
|
||||||
|
{
|
||||||
|
$dfd = new Deferred(function() {});
|
||||||
|
$result = $this->promises->convert($dfd);
|
||||||
|
|
||||||
|
$this->assertInstanceOf('GraphQL\Executor\Promise\Promise', $result);
|
||||||
|
$this->assertInstanceOf('GraphQL\Executor\Promise\Adapter\SyncPromise', $result->adoptedPromise);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->promises->convert('');
|
||||||
|
$this->fail('Expected exception no thrown');
|
||||||
|
} catch (InvariantViolation $e) {
|
||||||
|
$this->assertEquals('Expected instance of GraphQL\Deferred, got (empty string)', $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThen()
|
||||||
|
{
|
||||||
|
$dfd = new Deferred(function() {});
|
||||||
|
$promise = $this->promises->convert($dfd);
|
||||||
|
|
||||||
|
$result = $this->promises->then($promise);
|
||||||
|
|
||||||
|
$this->assertInstanceOf('GraphQL\Executor\Promise\Promise', $result);
|
||||||
|
$this->assertInstanceOf('GraphQL\Executor\Promise\Adapter\SyncPromise', $result->adoptedPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreatePromise()
|
||||||
|
{
|
||||||
|
$promise = $this->promises->createPromise(function($resolve, $reject) {});
|
||||||
|
|
||||||
|
$this->assertInstanceOf('GraphQL\Executor\Promise\Promise', $promise);
|
||||||
|
$this->assertInstanceOf('GraphQL\Executor\Promise\Adapter\SyncPromise', $promise->adoptedPromise);
|
||||||
|
|
||||||
|
$promise = $this->promises->createPromise(function($resolve, $reject) {
|
||||||
|
$resolve('A');
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertValidPromise($promise, null, 'A', SyncPromise::FULFILLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateFulfilledPromise()
|
||||||
|
{
|
||||||
|
$promise = $this->promises->createResolvedPromise('test');
|
||||||
|
$this->assertValidPromise($promise, null, 'test', SyncPromise::FULFILLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateRejectedPromise()
|
||||||
|
{
|
||||||
|
$promise = $this->promises->createRejectedPromise(new \Exception('test reason'));
|
||||||
|
$this->assertValidPromise($promise, 'test reason', null, SyncPromise::REJECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreatePromiseAll()
|
||||||
|
{
|
||||||
|
$promise = $this->promises->createPromiseAll([]);
|
||||||
|
$this->assertValidPromise($promise, null, [], SyncPromise::FULFILLED);
|
||||||
|
|
||||||
|
$promise = $this->promises->createPromiseAll(['1']);
|
||||||
|
$this->assertValidPromise($promise, null, ['1'], SyncPromise::FULFILLED);
|
||||||
|
|
||||||
|
$promise1 = new SyncPromise();
|
||||||
|
$promise2 = new SyncPromise();
|
||||||
|
$promise3 = $promise2->then(
|
||||||
|
function($value) {
|
||||||
|
return $value .'-value3';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'1',
|
||||||
|
new Promise($promise1, $this->promises),
|
||||||
|
new Promise($promise2, $this->promises),
|
||||||
|
3,
|
||||||
|
new Promise($promise3, $this->promises),
|
||||||
|
[]
|
||||||
|
];
|
||||||
|
|
||||||
|
$promise = $this->promises->createPromiseAll($data);
|
||||||
|
$this->assertValidPromise($promise, null, null, SyncPromise::PENDING);
|
||||||
|
|
||||||
|
$promise1->resolve('value1');
|
||||||
|
$this->assertValidPromise($promise, null, null, SyncPromise::PENDING);
|
||||||
|
$promise2->resolve('value2');
|
||||||
|
$this->assertValidPromise($promise, null, ['1', 'value1', 'value2', 3, 'value2-value3', []], SyncPromise::FULFILLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWait()
|
||||||
|
{
|
||||||
|
$called = [];
|
||||||
|
|
||||||
|
$deferred1 = new Deferred(function() use (&$called) {
|
||||||
|
$called[] = 1;
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
$deferred2 = new Deferred(function() use (&$called) {
|
||||||
|
$called[] = 2;
|
||||||
|
return 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
$p1 = $this->promises->convert($deferred1);
|
||||||
|
$p2 = $this->promises->convert($deferred2);
|
||||||
|
|
||||||
|
$p3 = $p2->then(function() use (&$called) {
|
||||||
|
$dfd = new Deferred(function() use (&$called) {
|
||||||
|
$called[] = 3;
|
||||||
|
return 3;
|
||||||
|
});
|
||||||
|
return $this->promises->convert($dfd);
|
||||||
|
});
|
||||||
|
|
||||||
|
$p4 = $p3->then(function() use (&$called) {
|
||||||
|
return new Deferred(function() use (&$called) {
|
||||||
|
$called[] = 4;
|
||||||
|
return 4;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$all = $this->promises->createPromiseAll([0, $p1, $p2, $p3, $p4]);
|
||||||
|
|
||||||
|
$result = $this->promises->wait($p2);
|
||||||
|
$this->assertEquals(2, $result);
|
||||||
|
$this->assertEquals(SyncPromise::PENDING, $p3->adoptedPromise->state);
|
||||||
|
$this->assertEquals(SyncPromise::PENDING, $all->adoptedPromise->state);
|
||||||
|
$this->assertEquals([1, 2], $called);
|
||||||
|
|
||||||
|
$expectedResult = [0,1,2,3,4];
|
||||||
|
$result = $this->promises->wait($all);
|
||||||
|
$this->assertEquals($expectedResult, $result);
|
||||||
|
$this->assertEquals([1, 2, 3, 4], $called);
|
||||||
|
$this->assertValidPromise($all, null, [0,1,2,3,4], SyncPromise::FULFILLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function assertValidPromise($promise, $expectedNextReason, $expectedNextValue, $expectedNextState)
|
||||||
|
{
|
||||||
|
$this->assertInstanceOf('GraphQL\Executor\Promise\Promise', $promise);
|
||||||
|
$this->assertInstanceOf('GraphQL\Executor\Promise\Adapter\SyncPromise', $promise->adoptedPromise);
|
||||||
|
|
||||||
|
$actualNextValue = null;
|
||||||
|
$actualNextReason = null;
|
||||||
|
$onFulfilledCalled = false;
|
||||||
|
$onRejectedCalled = false;
|
||||||
|
|
||||||
|
$promise->then(
|
||||||
|
function($nextValue) use (&$actualNextValue, &$onFulfilledCalled) {
|
||||||
|
$onFulfilledCalled = true;
|
||||||
|
$actualNextValue = $nextValue;
|
||||||
|
},
|
||||||
|
function(\Exception $reason) use (&$actualNextReason, &$onRejectedCalled) {
|
||||||
|
$onRejectedCalled = true;
|
||||||
|
$actualNextReason = $reason->getMessage();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals($onFulfilledCalled, false);
|
||||||
|
$this->assertEquals($onRejectedCalled, false);
|
||||||
|
|
||||||
|
SyncPromise::runQueue();
|
||||||
|
|
||||||
|
if ($expectedNextState !== SyncPromise::PENDING) {
|
||||||
|
$this->assertEquals(!$expectedNextReason, $onFulfilledCalled);
|
||||||
|
$this->assertEquals(!!$expectedNextReason, $onRejectedCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals($expectedNextValue, $actualNextValue);
|
||||||
|
$this->assertEquals($expectedNextReason, $actualNextReason);
|
||||||
|
$this->assertEquals($expectedNextState, $promise->adoptedPromise->state);
|
||||||
|
}
|
||||||
|
}
|
@ -252,12 +252,12 @@ class SyncPromiseTest extends \PHPUnit_Framework_TestCase
|
|||||||
$nextPromise3 = $promise->then($onFulfilled, $onRejected);
|
$nextPromise3 = $promise->then($onFulfilled, $onRejected);
|
||||||
$nextPromise4 = $promise->then($onFulfilled, $onRejected);
|
$nextPromise4 = $promise->then($onFulfilled, $onRejected);
|
||||||
|
|
||||||
$this->assertEquals(SyncPromise::$queue->count(), 0);
|
$this->assertEquals(SyncPromise::getQueue()->count(), 0);
|
||||||
$this->assertEquals($onFulfilledCount, 0);
|
$this->assertEquals($onFulfilledCount, 0);
|
||||||
$this->assertEquals($onRejectedCount, 0);
|
$this->assertEquals($onRejectedCount, 0);
|
||||||
$promise->resolve(1);
|
$promise->resolve(1);
|
||||||
|
|
||||||
$this->assertEquals(SyncPromise::$queue->count(), 4);
|
$this->assertEquals(SyncPromise::getQueue()->count(), 4);
|
||||||
$this->assertEquals($onFulfilledCount, 0);
|
$this->assertEquals($onFulfilledCount, 0);
|
||||||
$this->assertEquals($onRejectedCount, 0);
|
$this->assertEquals($onRejectedCount, 0);
|
||||||
$this->assertEquals(SyncPromise::PENDING, $nextPromise->state);
|
$this->assertEquals(SyncPromise::PENDING, $nextPromise->state);
|
||||||
@ -266,7 +266,7 @@ class SyncPromiseTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(SyncPromise::PENDING, $nextPromise4->state);
|
$this->assertEquals(SyncPromise::PENDING, $nextPromise4->state);
|
||||||
|
|
||||||
SyncPromise::runQueue();
|
SyncPromise::runQueue();
|
||||||
$this->assertEquals(SyncPromise::$queue->count(), 0);
|
$this->assertEquals(SyncPromise::getQueue()->count(), 0);
|
||||||
$this->assertEquals($onFulfilledCount, 3);
|
$this->assertEquals($onFulfilledCount, 3);
|
||||||
$this->assertEquals($onRejectedCount, 0);
|
$this->assertEquals($onRejectedCount, 0);
|
||||||
$this->assertValidPromise($nextPromise, null, 1, SyncPromise::FULFILLED);
|
$this->assertValidPromise($nextPromise, null, 1, SyncPromise::FULFILLED);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user