client = $client; parent::__construct(function($resolve, $reject) { return $this->cancel($resolve, $reject); }); } /** * Invoke $generator to create a \Generator which yields promises * * @param callable $generator as function():\Generator, creating a generator yielding promises * @return Invoker */ function invoke(callable $generator) : Invoker { $this->iterate($generator()); return $this; } /** * Iterate over $gen, a \Generator yielding promises * * @param Generator $gen * @return Invoker */ function iterate(Generator $gen) : Invoker { $this->cancelled = false; foreach ($gen as $promise) { if ($this->cancelled) { break; } $this->give($promise, $gen); } if (!$this->cancelled) { $this->resolve($this->result = $gen->getReturn()); } return $this; } /** * Get the generator's result * * @return ExtendedPromiseInterface */ function result() : ExtendedPromiseInterface { return $this->promise(); } /** * Promise handler * * @param array|PromiseInterface $promise * @param Generator $gen */ private function give($promise, Generator $gen) { if ($promise instanceof PromiseInterface) { $promise->then(function($result) use($gen) { if (($promise = $gen->send($result))) { $this->give($promise, $gen); } }); } else { all($promise)->then(function($results) use($gen) { if (($promise = $gen->send($results))) { $this->give($promise, $gen); } }); } $this->client->send(); } /** * Cancellation callback * * @param callable $resolve * @param callable $reject */ private function cancel(callable $resolve, callable $reject) { $this->cancelled = true; /* did we finish in the meantime? */ if ($this->result) { $resolve($this->result); } else { $reject("Cancelled"); } } }