123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- <?php
- declare(strict_types=1);
- namespace GuzzleHttp\Promise;
- use Generator;
- use Throwable;
- final class Coroutine implements PromiseInterface
- {
-
- private $currentPromise;
-
- private $generator;
-
- private $result;
- public function __construct(callable $generatorFn)
- {
- $this->generator = $generatorFn();
- $this->result = new Promise(function (): void {
- while (isset($this->currentPromise)) {
- $this->currentPromise->wait();
- }
- });
- try {
- $this->nextCoroutine($this->generator->current());
- } catch (Throwable $throwable) {
- $this->result->reject($throwable);
- }
- }
-
- public static function of(callable $generatorFn): self
- {
- return new self($generatorFn);
- }
- public function then(
- callable $onFulfilled = null,
- callable $onRejected = null
- ): PromiseInterface {
- return $this->result->then($onFulfilled, $onRejected);
- }
- public function otherwise(callable $onRejected): PromiseInterface
- {
- return $this->result->otherwise($onRejected);
- }
- public function wait(bool $unwrap = true)
- {
- return $this->result->wait($unwrap);
- }
- public function getState(): string
- {
- return $this->result->getState();
- }
- public function resolve($value): void
- {
- $this->result->resolve($value);
- }
- public function reject($reason): void
- {
- $this->result->reject($reason);
- }
- public function cancel(): void
- {
- $this->currentPromise->cancel();
- $this->result->cancel();
- }
- private function nextCoroutine($yielded): void
- {
- $this->currentPromise = Create::promiseFor($yielded)
- ->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
- }
-
- public function _handleSuccess($value): void
- {
- unset($this->currentPromise);
- try {
- $next = $this->generator->send($value);
- if ($this->generator->valid()) {
- $this->nextCoroutine($next);
- } else {
- $this->result->resolve($value);
- }
- } catch (Throwable $throwable) {
- $this->result->reject($throwable);
- }
- }
-
- public function _handleFailure($reason): void
- {
- unset($this->currentPromise);
- try {
- $nextYield = $this->generator->throw(Create::exceptionFor($reason));
-
- $this->nextCoroutine($nextYield);
- } catch (Throwable $throwable) {
- $this->result->reject($throwable);
- }
- }
- }
|