Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?phpnamespace GuzzleHttp\Promise;use Exception;use Generator;use Throwable;/*** Creates a promise that is resolved using a generator that yields values or* promises (somewhat similar to C#'s async keyword).** When called, the Coroutine::of method will start an instance of the generator* and returns a promise that is fulfilled with its final yielded value.** Control is returned back to the generator when the yielded promise settles.* This can lead to less verbose code when doing lots of sequential async calls* with minimal processing in between.** use GuzzleHttp\Promise;** function createPromise($value) {* return new Promise\FulfilledPromise($value);* }** $promise = Promise\Coroutine::of(function () {* $value = (yield createPromise('a'));* try {* $value = (yield createPromise($value . 'b'));* } catch (\Exception $e) {* // The promise was rejected.* }* yield $value . 'c';* });** // Outputs "abc"* $promise->then(function ($v) { echo $v; });** @param callable $generatorFn Generator function to wrap into a promise.** @return Promise** @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration*/final class Coroutine implements PromiseInterface{/*** @var PromiseInterface|null*/private $currentPromise;/*** @var Generator*/private $generator;/*** @var Promise*/private $result;public function __construct(callable $generatorFn){$this->generator = $generatorFn();$this->result = new Promise(function () {while (isset($this->currentPromise)) {$this->currentPromise->wait();}});try {$this->nextCoroutine($this->generator->current());} catch (\Exception $exception) {$this->result->reject($exception);} catch (Throwable $throwable) {$this->result->reject($throwable);}}/*** Create a new coroutine.** @return self*/public static function of(callable $generatorFn){return new self($generatorFn);}public function then(callable $onFulfilled = null,callable $onRejected = null) {return $this->result->then($onFulfilled, $onRejected);}public function otherwise(callable $onRejected){return $this->result->otherwise($onRejected);}public function wait($unwrap = true){return $this->result->wait($unwrap);}public function getState(){return $this->result->getState();}public function resolve($value){$this->result->resolve($value);}public function reject($reason){$this->result->reject($reason);}public function cancel(){$this->currentPromise->cancel();$this->result->cancel();}private function nextCoroutine($yielded){$this->currentPromise = Create::promiseFor($yielded)->then([$this, '_handleSuccess'], [$this, '_handleFailure']);}/*** @internal*/public function _handleSuccess($value){unset($this->currentPromise);try {$next = $this->generator->send($value);if ($this->generator->valid()) {$this->nextCoroutine($next);} else {$this->result->resolve($value);}} catch (Exception $exception) {$this->result->reject($exception);} catch (Throwable $throwable) {$this->result->reject($throwable);}}/*** @internal*/public function _handleFailure($reason){unset($this->currentPromise);try {$nextYield = $this->generator->throw(Create::exceptionFor($reason));// The throw was caught, so keep iterating on the coroutine$this->nextCoroutine($nextYield);} catch (Exception $exception) {$this->result->reject($exception);} catch (Throwable $throwable) {$this->result->reject($throwable);}}}