3
3
namespace Http \Adapter \React ;
4
4
5
5
use React \EventLoop \LoopInterface ;
6
- use React \Promise \PromiseInterface as ReactPromise ;
7
6
use Http \Client \Exception ;
8
7
use Http \Promise \Promise as HttpPromise ;
9
8
use Psr \Http \Message \ResponseInterface ;
12
11
* React promise adapter implementation.
13
12
*
14
13
* @author Stéphane Hulard <stephane@hlrd.me>
14
+ *
15
+ * @internal
15
16
*/
16
17
class Promise implements HttpPromise
17
18
{
@@ -22,13 +23,6 @@ class Promise implements HttpPromise
22
23
*/
23
24
private $ state = HttpPromise::PENDING ;
24
25
25
- /**
26
- * Adapted React promise.
27
- *
28
- * @var ReactPromise
29
- */
30
- private $ promise ;
31
-
32
26
/**
33
27
* PSR7 received response.
34
28
*
@@ -43,31 +37,26 @@ class Promise implements HttpPromise
43
37
*/
44
38
private $ exception ;
45
39
40
+ /**
41
+ * @var callable|null
42
+ */
43
+ private $ onFulfilled ;
44
+
45
+ /**
46
+ * @var callable|null
47
+ */
48
+ private $ onRejected ;
49
+
46
50
/**
47
51
* React Event Loop used for synchronous processing.
48
52
*
49
53
* @var LoopInterface
50
54
*/
51
55
private $ loop ;
52
56
53
- /**
54
- * Initialize the promise.
55
- *
56
- * @param ReactPromise $promise
57
- */
58
- public function __construct (ReactPromise $ promise )
57
+ public function __construct (LoopInterface $ loop )
59
58
{
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 ;
71
60
}
72
61
73
62
/**
@@ -80,49 +69,92 @@ function (Exception $error) {
80
69
*/
81
70
public function then (callable $ onFulfilled = null , callable $ onRejected = null )
82
71
{
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 );
86
87
}
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 );
90
95
}
91
- }) ;
96
+ };
92
97
93
- return $ this ;
98
+ return $ newPromise ;
94
99
}
95
100
96
101
/**
97
- * {@inheritdoc}
102
+ * Resolve this promise
103
+ *
104
+ * @param ResponseInterface $response
105
+ *
106
+ * @internal
98
107
*/
99
- public function getState ( )
108
+ public function resolve ( ResponseInterface $ response )
100
109
{
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
+ }
102
121
}
103
122
104
123
/**
105
- * Set EventLoop used for synchronous processing.
124
+ * Reject this promise
106
125
*
107
- * @param LoopInterface $loop
126
+ * @param Exception $exception
108
127
*
109
- * @return Promise
128
+ * @internal
110
129
*/
111
- public function setLoop ( LoopInterface $ loop )
130
+ public function reject ( Exception $ exception )
112
131
{
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 ;
114
139
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 ;
116
151
}
117
152
118
153
/**
119
154
* {@inheritdoc}
120
155
*/
121
156
public function wait ($ unwrap = true )
122
157
{
123
- if (null === $ this ->loop ) {
124
- throw new \LogicException ('You must set the loop before wait! ' );
125
- }
126
158
while (HttpPromise::PENDING === $ this ->getState ()) {
127
159
$ this ->loop ->tick ();
128
160
}
0 commit comments