33namespace Http \Adapter \React ;
44
55use React \EventLoop \LoopInterface ;
6- use React \Promise \PromiseInterface as ReactPromise ;
76use Http \Client \Exception ;
87use Http \Promise \Promise as HttpPromise ;
98use Psr \Http \Message \ResponseInterface ;
1211 * React promise adapter implementation.
1312 *
1413 * @author Stéphane Hulard <stephane@hlrd.me>
14+ *
15+ * @internal
1516 */
1617class Promise implements HttpPromise
1718{
@@ -22,13 +23,6 @@ class Promise implements HttpPromise
2223 */
2324 private $ state = HttpPromise::PENDING ;
2425
25- /**
26- * Adapted React promise.
27- *
28- * @var ReactPromise
29- */
30- private $ promise ;
31-
3226 /**
3327 * PSR7 received response.
3428 *
@@ -43,31 +37,26 @@ class Promise implements HttpPromise
4337 */
4438 private $ exception ;
4539
40+ /**
41+ * @var callable|null
42+ */
43+ private $ onFulfilled ;
44+
45+ /**
46+ * @var callable|null
47+ */
48+ private $ onRejected ;
49+
4650 /**
4751 * React Event Loop used for synchronous processing.
4852 *
4953 * @var LoopInterface
5054 */
5155 private $ loop ;
5256
53- /**
54- * Initialize the promise.
55- *
56- * @param ReactPromise $promise
57- */
58- public function __construct (ReactPromise $ promise )
57+ public function __construct (LoopInterface $ loop )
5958 {
60- $ promise ->then (
61- function (ResponseInterface $ response ) {
62- $ this ->state = HttpPromise::FULFILLED ;
63- $ this ->response = $ response ;
64- },
65- function (Exception $ error ) {
66- $ this ->state = HttpPromise::REJECTED ;
67- $ this ->exception = $ error ;
68- }
69- );
70- $ this ->promise = $ promise ;
59+ $ this ->loop = $ loop ;
7160 }
7261
7362 /**
@@ -80,49 +69,92 @@ function (Exception $error) {
8069 */
8170 public function then (callable $ onFulfilled = null , callable $ onRejected = null )
8271 {
83- $ this ->promise ->then (function () use ($ onFulfilled ) {
84- if (null !== $ onFulfilled ) {
85- call_user_func ($ onFulfilled , $ this ->response );
72+ $ newPromise = new Promise ($ this ->loop );
73+
74+ $ onFulfilled = $ onFulfilled !== null ? $ onFulfilled : function (ResponseInterface $ response ) {
75+ return $ response ;
76+ };
77+
78+ $ onRejected = $ onRejected !== null ? $ onRejected : function (Exception $ exception ) {
79+ throw $ exception ;
80+ };
81+
82+ $ this ->onFulfilled = function (ResponseInterface $ response ) use ($ onFulfilled , $ newPromise ) {
83+ try {
84+ $ newPromise ->resolve ($ onFulfilled ($ response ));
85+ } catch (Exception $ exception ) {
86+ $ newPromise ->reject ($ exception );
8687 }
87- }, function () use ($ onRejected ) {
88- if (null !== $ onRejected ) {
89- call_user_func ($ onRejected , $ this ->exception );
88+ };
89+
90+ $ this ->onRejected = function (Exception $ exception ) use ($ onRejected , $ newPromise ) {
91+ try {
92+ $ newPromise ->resolve ($ onRejected ($ exception ));
93+ } catch (Exception $ exception ) {
94+ $ newPromise ->reject ($ exception );
9095 }
91- }) ;
96+ };
9297
93- return $ this ;
98+ return $ newPromise ;
9499 }
95100
96101 /**
97- * {@inheritdoc}
102+ * Resolve this promise
103+ *
104+ * @param ResponseInterface $response
105+ *
106+ * @internal
98107 */
99- public function getState ( )
108+ public function resolve ( ResponseInterface $ response )
100109 {
101- return $ this ->state ;
110+ if ($ this ->state !== HttpPromise::PENDING ) {
111+ throw new \RuntimeException ('Promise is already resolved ' );
112+ }
113+
114+ $ this ->state = HttpPromise::FULFILLED ;
115+ $ this ->response = $ response ;
116+ $ onFulfilled = $ this ->onFulfilled ;
117+
118+ if (null !== $ onFulfilled ) {
119+ $ onFulfilled ($ response );
120+ }
102121 }
103122
104123 /**
105- * Set EventLoop used for synchronous processing.
124+ * Reject this promise
106125 *
107- * @param LoopInterface $loop
126+ * @param Exception $exception
108127 *
109- * @return Promise
128+ * @internal
110129 */
111- public function setLoop ( LoopInterface $ loop )
130+ public function reject ( Exception $ exception )
112131 {
113- $ this ->loop = $ loop ;
132+ if ($ this ->state !== HttpPromise::PENDING ) {
133+ throw new \RuntimeException ('Promise is already resolved ' );
134+ }
135+
136+ $ this ->state = HttpPromise::REJECTED ;
137+ $ this ->exception = $ exception ;
138+ $ onRejected = $ this ->onRejected ;
114139
115- return $ this ;
140+ if (null !== $ onRejected ) {
141+ $ onRejected ($ exception );
142+ }
143+ }
144+
145+ /**
146+ * {@inheritdoc}
147+ */
148+ public function getState ()
149+ {
150+ return $ this ->state ;
116151 }
117152
118153 /**
119154 * {@inheritdoc}
120155 */
121156 public function wait ($ unwrap = true )
122157 {
123- if (null === $ this ->loop ) {
124- throw new \LogicException ('You must set the loop before wait! ' );
125- }
126158 while (HttpPromise::PENDING === $ this ->getState ()) {
127159 $ this ->loop ->tick ();
128160 }
0 commit comments