@@ -68,36 +68,45 @@ function reject(\Throwable $reason): PromiseInterface
68
68
* will be an array containing the resolution values of each of the items in
69
69
* `$promisesOrValues`.
70
70
*
71
- * @param array $promisesOrValues
71
+ * @param iterable $promisesOrValues
72
72
* @return PromiseInterface
73
73
*/
74
- function all (array $ promisesOrValues ): PromiseInterface
74
+ function all (iterable $ promisesOrValues ): PromiseInterface
75
75
{
76
- if (!$ promisesOrValues ) {
77
- return resolve ([]);
78
- }
79
-
80
76
$ cancellationQueue = new Internal \CancellationQueue ();
81
77
82
78
return new Promise (function ($ resolve , $ reject ) use ($ promisesOrValues , $ cancellationQueue ): void {
83
- $ toResolve = \count ($ promisesOrValues );
79
+ $ toResolve = 0 ;
80
+ $ continue = true ;
84
81
$ values = [];
85
82
86
83
foreach ($ promisesOrValues as $ i => $ promiseOrValue ) {
87
84
$ cancellationQueue ->enqueue ($ promiseOrValue );
88
85
$ values [$ i ] = null ;
86
+ ++$ toResolve ;
87
+
88
+ resolve ($ promiseOrValue )->then (
89
+ function ($ value ) use ($ i , &$ values , &$ toResolve , &$ continue , $ resolve ): void {
90
+ $ values [$ i ] = $ value ;
91
+
92
+ if (0 === --$ toResolve && !$ continue ) {
93
+ $ resolve ($ values );
94
+ }
95
+ },
96
+ function (\Throwable $ reason ) use (&$ continue , $ reject ): void {
97
+ $ continue = false ;
98
+ $ reject ($ reason );
99
+ }
100
+ );
101
+
102
+ if (!$ continue ) {
103
+ break ;
104
+ }
105
+ }
89
106
90
- resolve ($ promiseOrValue )
91
- ->then (
92
- function ($ mapped ) use ($ i , &$ values , &$ toResolve , $ resolve ): void {
93
- $ values [$ i ] = $ mapped ;
94
-
95
- if (0 === --$ toResolve ) {
96
- $ resolve ($ values );
97
- }
98
- },
99
- $ reject
100
- );
107
+ $ continue = false ;
108
+ if ($ toResolve === 0 ) {
109
+ $ resolve ($ values );
101
110
}
102
111
}, $ cancellationQueue );
103
112
}
@@ -109,23 +118,26 @@ function ($mapped) use ($i, &$values, &$toResolve, $resolve): void {
109
118
* The returned promise will become **infinitely pending** if `$promisesOrValues`
110
119
* contains 0 items.
111
120
*
112
- * @param array $promisesOrValues
121
+ * @param iterable $promisesOrValues
113
122
* @return PromiseInterface
114
123
*/
115
- function race (array $ promisesOrValues ): PromiseInterface
124
+ function race (iterable $ promisesOrValues ): PromiseInterface
116
125
{
117
- if (!$ promisesOrValues ) {
118
- return new Promise (function (): void {});
119
- }
120
-
121
126
$ cancellationQueue = new Internal \CancellationQueue ();
122
127
123
128
return new Promise (function ($ resolve , $ reject ) use ($ promisesOrValues , $ cancellationQueue ): void {
129
+ $ continue = true ;
130
+
124
131
foreach ($ promisesOrValues as $ promiseOrValue ) {
125
132
$ cancellationQueue ->enqueue ($ promiseOrValue );
126
133
127
- resolve ($ promiseOrValue )
128
- ->then ($ resolve , $ reject );
134
+ resolve ($ promiseOrValue )->then ($ resolve , $ reject )->finally (function () use (&$ continue ): void {
135
+ $ continue = false ;
136
+ });
137
+
138
+ if (!$ continue ) {
139
+ break ;
140
+ }
129
141
}
130
142
}, $ cancellationQueue );
131
143
}
@@ -141,53 +153,54 @@ function race(array $promisesOrValues): PromiseInterface
141
153
* The returned promise will also reject with a `React\Promise\Exception\LengthException`
142
154
* if `$promisesOrValues` contains 0 items.
143
155
*
144
- * @param array $promisesOrValues
156
+ * @param iterable $promisesOrValues
145
157
* @return PromiseInterface
146
158
*/
147
- function any (array $ promisesOrValues ): PromiseInterface
159
+ function any (iterable $ promisesOrValues ): PromiseInterface
148
160
{
149
- $ len = \count ($ promisesOrValues );
150
-
151
- if (!$ promisesOrValues ) {
152
- return reject (
153
- new Exception \LengthException (
154
- \sprintf (
155
- 'Input array must contain at least 1 item but contains only %s item%s. ' ,
156
- $ len ,
157
- 1 === $ len ? '' : 's '
158
- )
159
- )
160
- );
161
- }
162
-
163
161
$ cancellationQueue = new Internal \CancellationQueue ();
164
162
165
- return new Promise (function ($ resolve , $ reject ) use ($ len , $ promisesOrValues , $ cancellationQueue ): void {
166
- $ toReject = $ len ;
167
- $ reasons = [];
163
+ return new Promise (function ($ resolve , $ reject ) use ($ promisesOrValues , $ cancellationQueue ): void {
164
+ $ toReject = 0 ;
165
+ $ continue = true ;
166
+ $ reasons = [];
168
167
169
168
foreach ($ promisesOrValues as $ i => $ promiseOrValue ) {
170
- $ fulfiller = function ($ val ) use ($ resolve ): void {
171
- $ resolve ($ val );
172
- };
173
-
174
- $ rejecter = function (\Throwable $ reason ) use ($ i , &$ reasons , &$ toReject , $ reject ): void {
175
- $ reasons [$ i ] = $ reason ;
176
-
177
- if (0 === --$ toReject ) {
178
- $ reject (
179
- new CompositeException (
169
+ $ cancellationQueue ->enqueue ($ promiseOrValue );
170
+ ++$ toReject ;
171
+
172
+ resolve ($ promiseOrValue )->then (
173
+ function ($ value ) use ($ resolve , &$ continue ): void {
174
+ $ continue = false ;
175
+ $ resolve ($ value );
176
+ },
177
+ function (\Throwable $ reason ) use ($ i , &$ reasons , &$ toReject , $ reject , &$ continue ): void {
178
+ $ reasons [$ i ] = $ reason ;
179
+
180
+ if (0 === --$ toReject && !$ continue ) {
181
+ $ reject (new CompositeException (
180
182
$ reasons ,
181
183
'All promises rejected. '
182
- )
183
- );
184
+ ));
185
+ }
184
186
}
185
- } ;
187
+ ) ;
186
188
187
- $ cancellationQueue ->enqueue ($ promiseOrValue );
189
+ if (!$ continue ) {
190
+ break ;
191
+ }
192
+ }
188
193
189
- resolve ($ promiseOrValue )
190
- ->then ($ fulfiller , $ rejecter );
194
+ $ continue = false ;
195
+ if ($ toReject === 0 && !$ reasons ) {
196
+ $ reject (new Exception \LengthException (
197
+ 'Must contain at least 1 item but contains only 0 items. '
198
+ ));
199
+ } elseif ($ toReject === 0 ) {
200
+ $ reject (new CompositeException (
201
+ $ reasons ,
202
+ 'All promises rejected. '
203
+ ));
191
204
}
192
205
}, $ cancellationQueue );
193
206
}
0 commit comments