7 use React\Promise\Deferred
;
8 use React\Promise\PromiseInterface
;
9 use React\Promise\ExtendedPromiseInterface
;
11 use function React\Promise\all
;
13 class Invoker
extends Deferred
22 * The return value of the generator
31 private $cancelled = false;
34 * Create a new generator invoker
35 * @param \http\Client $client
37 function __construct(Client
$client) {
38 $this->client
= $client;
40 parent
::__construct(function($resolve, $reject) {
41 return $this->cancel($resolve, $reject);
46 * Invoke $generator to create a \Generator which yields promises
48 * @param callable $generator as function() : \Generator, creating a generator yielding promises
49 * @return \seekat\API\Invoker
51 function invoke(callable
$generator) : Invoker
{
52 $this->iterate($generator());
57 * Iterate over $gen, a \Generator yielding promises
59 * @param \Generator $gen
60 * @return \seekat\API\Invoker
62 function iterate(Generator
$gen) : Invoker
{
63 $this->cancelled
= false;
65 foreach ($gen as $promise) {
66 if ($this->cancelled
) {
69 $this->queue($promise, $gen);
72 if (!$this->cancelled
) {
73 $this->resolve($this->result
= $gen->getReturn());
79 * Get the generator's result
81 * @return \React\Promise\ExtendedPromiseInterface
83 function result() : ExtendedPromiseInterface
{
84 return $this->promise();
90 * @param \React\Promise\PromiseInterface $promise
91 * @param \Generator $to
93 private function give(PromiseInterface
$promise, Generator
$to) {
94 $promise->then(function($result) use($to) {
95 if (($promise = $to->send($result))) {
96 $this->queue($promise, $to);
101 private function queue($promise, Generator
$gen) {
102 if ($promise instanceof PromiseInterface
) {
103 $this->give($promise, $gen);
105 all($promise)->then(function($results) use($gen) {
106 if (($promise = $gen->send($results))) {
107 $this->queue($promise, $gen);
111 $this->client
->send();
115 * Cancellation callback
117 * @param callable $resolve
118 * @param callable $reject
120 private function cancel(callable
$resolve, callable
$reject) {
121 $this->cancelled
= true;
123 /* did we finish in the meantime? */
125 $resolve($this->result
);
127 $reject("Cancelled");