@@ -11,7 +11,6 @@ class Promise implements ExtendedPromiseInterface, CancellablePromiseInterface
11
11
private $ progressHandlers = [];
12
12
13
13
private $ requiredCancelRequests = 0 ;
14
- private $ cancelRequests = 0 ;
15
14
16
15
public function __construct (callable $ resolver , callable $ canceller = null )
17
16
{
@@ -32,11 +31,11 @@ public function then(callable $onFulfilled = null, callable $onRejected = null,
32
31
$ this ->requiredCancelRequests ++;
33
32
34
33
return new static ($ this ->resolver ($ onFulfilled , $ onRejected , $ onProgress ), function () {
35
- if (++$ this ->cancelRequests < $ this ->requiredCancelRequests ) {
36
- return ;
37
- }
34
+ $ this ->requiredCancelRequests --;
38
35
39
- $ this ->cancel ();
36
+ if ($ this ->requiredCancelRequests <= 0 ) {
37
+ $ this ->cancel ();
38
+ }
40
39
});
41
40
}
42
41
@@ -87,14 +86,37 @@ public function progress(callable $onProgress)
87
86
88
87
public function cancel ()
89
88
{
90
- if (null === $ this ->canceller || null !== $ this ->result ) {
91
- return ;
92
- }
93
-
94
89
$ canceller = $ this ->canceller ;
95
90
$ this ->canceller = null ;
96
91
97
- $ this ->call ($ canceller );
92
+ $ parentCanceller = null ;
93
+
94
+ if (null !== $ this ->result ) {
95
+ // Go up the promise chain and reach the top most promise which is
96
+ // itself not following another promise
97
+ $ root = $ this ->unwrap ($ this ->result );
98
+
99
+ // Return if the root promise is already resolved or a
100
+ // FulfilledPromise or RejectedPromise
101
+ if (!$ root instanceof self || null !== $ root ->result ) {
102
+ return ;
103
+ }
104
+
105
+ $ root ->requiredCancelRequests --;
106
+
107
+ if ($ root ->requiredCancelRequests <= 0 ) {
108
+ $ parentCanceller = [$ root , 'cancel ' ];
109
+ }
110
+ }
111
+
112
+ if (null !== $ canceller ) {
113
+ $ this ->call ($ canceller );
114
+ }
115
+
116
+ // For BC, we call the parent canceller after our own canceller
117
+ if ($ parentCanceller ) {
118
+ $ parentCanceller ();
119
+ }
98
120
}
99
121
100
122
private function resolver (callable $ onFulfilled = null , callable $ onRejected = null , callable $ onProgress = null )
@@ -157,6 +179,16 @@ private function settle(ExtendedPromiseInterface $promise)
157
179
{
158
180
$ promise = $ this ->unwrap ($ promise );
159
181
182
+ if ($ promise === $ this ) {
183
+ $ promise = new RejectedPromise (
184
+ new \LogicException ('Cannot resolve a promise with itself. ' )
185
+ );
186
+ }
187
+
188
+ if ($ promise instanceof self) {
189
+ $ promise ->requiredCancelRequests ++;
190
+ }
191
+
160
192
$ handlers = $ this ->handlers ;
161
193
162
194
$ this ->progressHandlers = $ this ->handlers = [];
@@ -184,12 +216,6 @@ private function extract($promise)
184
216
$ promise = $ promise ->promise ();
185
217
}
186
218
187
- if ($ promise === $ this ) {
188
- return new RejectedPromise (
189
- new \LogicException ('Cannot resolve a promise with itself. ' )
190
- );
191
- }
192
-
193
219
return $ promise ;
194
220
}
195
221
0 commit comments