PluginProbe
Depicter — Popup & Slider Builder / 1.3.3
Depicter — Popup & Slider Builder v1.3.3
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / modules / GuzzleHttp / Promise / Coroutine.php

Coroutine.php in Depicter — Popup & Slider Builder 1.3.3, at modules/GuzzleHttp/Promise/Coroutine.php

170 lines 4.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Depicter\GuzzleHttp\Promise;
4
5 use Exception;
6 use Generator;
7 use Throwable;
8
9 /**
10 * Creates a promise that is resolved using a generator that yields values or
11 * promises (somewhat similar to C#'s async keyword).
12 *
13 * When called, the Coroutine::of method will start an instance of the generator
14 * and returns a promise that is fulfilled with its final yielded value.
15 *
16 * Control is returned back to the generator when the yielded promise settles.
17 * This can lead to less verbose code when doing lots of sequential async calls
18 * with minimal processing in between.
19 *
20 * use Depicter\GuzzleHttp\Promise;
21 *
22 * function createPromise($value) {
23 * return new Promise\FulfilledPromise($value);
24 * }
25 *
26 * $promise = Promise\Coroutine::of(function () {
27 * $value = (yield createPromise('a'));
28 * try {
29 * $value = (yield createPromise($value . 'b'));
30 * } catch (\Exception $e) {
31 * // The promise was rejected.
32 * }
33 * yield $value . 'c';
34 * });
35 *
36 * // Outputs "abc"
37 * $promise->then(function ($v) { echo $v; });
38 *
39 * @param callable $generatorFn Generator function to wrap into a promise.
40 *
41 * @return Promise
42 *
43 * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
44 */
45 final class Coroutine implements PromiseInterface
46 {
47 /**
48 * @var PromiseInterface|null
49 */
50 private $currentPromise;
51
52 /**
53 * @var Generator
54 */
55 private $generator;
56
57 /**
58 * @var Promise
59 */
60 private $result;
61
62 public function __construct(callable $generatorFn)
63 {
64 $this->generator = $generatorFn();
65 $this->result = new Promise(function () {
66 while (isset($this->currentPromise)) {
67 $this->currentPromise->wait();
68 }
69 });
70 try {
71 $this->nextCoroutine($this->generator->current());
72 } catch (\Exception $exception) {
73 $this->result->reject($exception);
74 } catch (Throwable $throwable) {
75 $this->result->reject($throwable);
76 }
77 }
78
79 /**
80 * Create a new coroutine.
81 *
82 * @return self
83 */
84 public static function of(callable $generatorFn)
85 {
86 return new self($generatorFn);
87 }
88
89 public function then(
90 callable $onFulfilled = null,
91 callable $onRejected = null
92 ) {
93 return $this->result->then($onFulfilled, $onRejected);
94 }
95
96 public function otherwise(callable $onRejected)
97 {
98 return $this->result->otherwise($onRejected);
99 }
100
101 public function wait($unwrap = true)
102 {
103 return $this->result->wait($unwrap);
104 }
105
106 public function getState()
107 {
108 return $this->result->getState();
109 }
110
111 public function resolve($value)
112 {
113 $this->result->resolve($value);
114 }
115
116 public function reject($reason)
117 {
118 $this->result->reject($reason);
119 }
120
121 public function cancel()
122 {
123 $this->currentPromise->cancel();
124 $this->result->cancel();
125 }
126
127 private function nextCoroutine($yielded)
128 {
129 $this->currentPromise = Create::promiseFor($yielded)
130 ->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
131 }
132
133 /**
134 * @internal
135 */
136 public function _handleSuccess($value)
137 {
138 unset($this->currentPromise);
139 try {
140 $next = $this->generator->send($value);
141 if ($this->generator->valid()) {
142 $this->nextCoroutine($next);
143 } else {
144 $this->result->resolve($value);
145 }
146 } catch (Exception $exception) {
147 $this->result->reject($exception);
148 } catch (Throwable $throwable) {
149 $this->result->reject($throwable);
150 }
151 }
152
153 /**
154 * @internal
155 */
156 public function _handleFailure($reason)
157 {
158 unset($this->currentPromise);
159 try {
160 $nextYield = $this->generator->throw(Create::exceptionFor($reason));
161 // The throw was caught, so keep iterating on the coroutine
162 $this->nextCoroutine($nextYield);
163 } catch (Exception $exception) {
164 $this->result->reject($exception);
165 } catch (Throwable $throwable) {
166 $this->result->reject($throwable);
167 }
168 }
169 }
170