@@ -73,35 +73,40 @@ function reject(\Throwable $reason): PromiseInterface
7373 */
7474function all (iterable $ promisesOrValues ): PromiseInterface
7575{
76- if (!\is_array ($ promisesOrValues )) {
77- $ promisesOrValues = \iterator_to_array ($ promisesOrValues );
78- }
79-
80- if (!$ promisesOrValues ) {
81- return resolve ([]);
82- }
83-
8476 $ cancellationQueue = new Internal \CancellationQueue ();
8577
8678 return new Promise (function ($ resolve , $ reject ) use ($ promisesOrValues , $ cancellationQueue ): void {
87- $ toResolve = \count ($ promisesOrValues );
79+ $ toResolve = 0 ;
80+ $ continue = true ;
8881 $ values = [];
8982
9083 foreach ($ promisesOrValues as $ i => $ promiseOrValue ) {
9184 $ cancellationQueue ->enqueue ($ promiseOrValue );
9285 $ 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+ );
93101
94- resolve ($ promiseOrValue )
95- ->then (
96- function ($ mapped ) use ($ i , &$ values , &$ toResolve , $ resolve ): void {
97- $ values [$ i ] = $ mapped ;
98-
99- if (0 === --$ toResolve ) {
100- $ resolve ($ values );
101- }
102- },
103- $ reject
104- );
102+ if (!$ continue ) {
103+ break ;
104+ }
105+ }
106+
107+ $ continue = false ;
108+ if ($ toResolve === 0 ) {
109+ $ resolve ($ values );
105110 }
106111 }, $ cancellationQueue );
107112}
@@ -118,22 +123,21 @@ function ($mapped) use ($i, &$values, &$toResolve, $resolve): void {
118123 */
119124function race (iterable $ promisesOrValues ): PromiseInterface
120125{
121- if (!\is_array ($ promisesOrValues )) {
122- $ promisesOrValues = \iterator_to_array ($ promisesOrValues );
123- }
124-
125- if (!$ promisesOrValues ) {
126- return new Promise (function (): void {});
127- }
128-
129126 $ cancellationQueue = new Internal \CancellationQueue ();
130127
131128 return new Promise (function ($ resolve , $ reject ) use ($ promisesOrValues , $ cancellationQueue ): void {
129+ $ continue = true ;
130+
132131 foreach ($ promisesOrValues as $ promiseOrValue ) {
133132 $ cancellationQueue ->enqueue ($ promiseOrValue );
134133
135- resolve ($ promiseOrValue )
136- ->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+ }
137141 }
138142 }, $ cancellationQueue );
139143}
@@ -154,52 +158,49 @@ function race(iterable $promisesOrValues): PromiseInterface
154158 */
155159function any (iterable $ promisesOrValues ): PromiseInterface
156160{
157- if (!\is_array ($ promisesOrValues )) {
158- $ promisesOrValues = \iterator_to_array ($ promisesOrValues );
159- }
160-
161- $ len = \count ($ promisesOrValues );
162-
163- if (!$ promisesOrValues ) {
164- return reject (
165- new Exception \LengthException (
166- \sprintf (
167- 'Must contain at least 1 item but contains only %s item%s. ' ,
168- $ len ,
169- 1 === $ len ? '' : 's '
170- )
171- )
172- );
173- }
174-
175161 $ cancellationQueue = new Internal \CancellationQueue ();
176162
177- return new Promise (function ($ resolve , $ reject ) use ($ len , $ promisesOrValues , $ cancellationQueue ): void {
178- $ toReject = $ len ;
179- $ reasons = [];
163+ return new Promise (function ($ resolve , $ reject ) use ($ promisesOrValues , $ cancellationQueue ): void {
164+ $ toReject = 0 ;
165+ $ continue = true ;
166+ $ reasons = [];
180167
181168 foreach ($ promisesOrValues as $ i => $ promiseOrValue ) {
182- $ fulfiller = function ($ val ) use ($ resolve ): void {
183- $ resolve ($ val );
184- };
185-
186- $ rejecter = function (\Throwable $ reason ) use ($ i , &$ reasons , &$ toReject , $ reject ): void {
187- $ reasons [$ i ] = $ reason ;
188-
189- if (0 === --$ toReject ) {
190- $ reject (
191- 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 (
192182 $ reasons ,
193183 'All promises rejected. '
194- )
195- );
184+ ));
185+ }
196186 }
197- } ;
187+ ) ;
198188
199- $ cancellationQueue ->enqueue ($ promiseOrValue );
189+ if (!$ continue ) {
190+ break ;
191+ }
192+ }
200193
201- resolve ($ promiseOrValue )
202- ->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+ ));
203204 }
204205 }, $ cancellationQueue );
205206}
0 commit comments