Skip to content

Commit 16052d3

Browse files
authored
Merge pull request #219 from clue-labs/less-functions
[RFC] Remove `some()`, `map()`, `reduce()` functions
2 parents 4bc784e + 5137c81 commit 16052d3

File tree

6 files changed

+39
-763
lines changed

6 files changed

+39
-763
lines changed

README.md

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ Table of Contents
4242
* [all()](#all)
4343
* [race()](#race)
4444
* [any()](#any)
45-
* [some()](#some)
46-
* [map()](#map)
47-
* [reduce()](#reduce)
4845
4. [Examples](#examples)
4946
* [How to use Deferred](#how-to-use-deferred)
5047
* [How promise forwarding works](#how-promise-forwarding-works)
@@ -365,10 +362,9 @@ once all consumers called the `cancel()` method of the promise.
365362

366363
### Functions
367364

368-
Useful functions for creating, joining, mapping and reducing collections of
369-
promises.
365+
Useful functions for creating and joining collections of promises.
370366

371-
All functions working on promise collections (like `all()`, `race()`, `some()`
367+
All functions working on promise collections (like `all()`, `race()`,
372368
etc.) support cancellation. This means, if you call `cancel()` on the returned
373369
promise, all promises in the collection are cancelled.
374370

@@ -442,49 +438,6 @@ which holds all rejection reasons. The rejection reasons can be obtained with
442438
The returned promise will also reject with a `React\Promise\Exception\LengthException`
443439
if `$promisesOrValues` contains 0 items.
444440

445-
#### some()
446-
447-
```php
448-
$promise = React\Promise\some(array $promisesOrValues, integer $howMany);
449-
```
450-
451-
Returns a promise that will resolve when at least `$howMany` of the supplied items in
452-
`$promisesOrValues` fulfill. The resolution value of the returned promise
453-
will be an array of length `$howMany` containing the resolution values of
454-
`$howMany` fulfilled promises that were resolved first.
455-
456-
The returned promise will reject if it becomes impossible for `$howMany` items
457-
to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items
458-
reject). The rejection value will be a `React\Promise\Exception\CompositeException`
459-
which holds `(count($promisesOrValues) - $howMany) + 1` rejection reasons.
460-
The rejection reasons can be obtained with `CompositeException::getExceptions()`.
461-
462-
The returned promise will also reject with a `React\Promise\Exception\LengthException`
463-
if `$promisesOrValues` contains less items than `$howMany`.
464-
465-
#### map()
466-
467-
```php
468-
$promise = React\Promise\map(array $promisesOrValues, callable $mapFunc);
469-
```
470-
471-
Traditional map function, similar to `array_map()`, but allows input to contain
472-
promises and/or values, and `$mapFunc` may return either a value or a promise.
473-
474-
The map function receives each item as argument, where item is a fully resolved
475-
value of a promise or value in `$promisesOrValues`.
476-
477-
#### reduce()
478-
479-
```php
480-
$promise = React\Promise\reduce(array $promisesOrValues, callable $reduceFunc, $initialValue = null);
481-
```
482-
483-
Traditional reduce function, similar to `array_reduce()`, but input may contain
484-
promises and/or values, and `$reduceFunc` may return either a value or a
485-
promise, *and* `$initialValue` may be a promise or a value for the starting
486-
value.
487-
488441
Examples
489442
--------
490443

src/functions.php

Lines changed: 35 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,33 @@ function reject(\Throwable $reason): PromiseInterface
7373
*/
7474
function all(array $promisesOrValues): PromiseInterface
7575
{
76-
return map($promisesOrValues, function ($val) {
77-
return $val;
78-
});
76+
if (!$promisesOrValues) {
77+
return resolve([]);
78+
}
79+
80+
$cancellationQueue = new Internal\CancellationQueue();
81+
82+
return new Promise(function ($resolve, $reject) use ($promisesOrValues, $cancellationQueue): void {
83+
$toResolve = \count($promisesOrValues);
84+
$values = [];
85+
86+
foreach ($promisesOrValues as $i => $promiseOrValue) {
87+
$cancellationQueue->enqueue($promiseOrValue);
88+
$values[$i] = null;
89+
90+
resolve($promiseOrValue)
91+
->done(
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+
);
101+
}
102+
}, $cancellationQueue);
79103
}
80104

81105
/**
@@ -122,45 +146,13 @@ function race(array $promisesOrValues): PromiseInterface
122146
*/
123147
function any(array $promisesOrValues): PromiseInterface
124148
{
125-
return some($promisesOrValues, 1)
126-
->then(function ($val) {
127-
return \array_shift($val);
128-
});
129-
}
130-
131-
/**
132-
* Returns a promise that will resolve when `$howMany` of the supplied items in
133-
* `$promisesOrValues` resolve. The resolution value of the returned promise
134-
* will be an array of length `$howMany` containing the resolution values of the
135-
* triggering items.
136-
*
137-
* The returned promise will reject if it becomes impossible for `$howMany` items
138-
* to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items
139-
* reject). The rejection value will be an array of
140-
* `(count($promisesOrValues) - $howMany) + 1` rejection reasons.
141-
*
142-
* The returned promise will also reject with a `React\Promise\Exception\LengthException`
143-
* if `$promisesOrValues` contains less items than `$howMany`.
144-
*
145-
* @param array $promisesOrValues
146-
* @param int $howMany
147-
* @return PromiseInterface
148-
*/
149-
function some(array $promisesOrValues, int $howMany): PromiseInterface
150-
{
151-
if ($howMany < 1) {
152-
return resolve([]);
153-
}
154-
155149
$len = \count($promisesOrValues);
156150

157-
if ($len < $howMany) {
151+
if (!$promisesOrValues) {
158152
return reject(
159153
new Exception\LengthException(
160154
\sprintf(
161-
'Input array must contain at least %d item%s but contains only %s item%s.',
162-
$howMany,
163-
1 === $howMany ? '' : 's',
155+
'Input array must contain at least 1 item but contains only %s item%s.',
164156
$len,
165157
1 === $len ? '' : 's'
166158
)
@@ -170,37 +162,23 @@ function some(array $promisesOrValues, int $howMany): PromiseInterface
170162

171163
$cancellationQueue = new Internal\CancellationQueue();
172164

173-
return new Promise(function ($resolve, $reject) use ($len, $promisesOrValues, $howMany, $cancellationQueue): void {
174-
$toResolve = $howMany;
175-
$toReject = ($len - $toResolve) + 1;
176-
$values = [];
165+
return new Promise(function ($resolve, $reject) use ($len, $promisesOrValues, $cancellationQueue): void {
166+
$toReject = $len;
177167
$reasons = [];
178168

179169
foreach ($promisesOrValues as $i => $promiseOrValue) {
180-
$fulfiller = function ($val) use ($i, &$values, &$toResolve, $toReject, $resolve): void {
181-
if ($toResolve < 1 || $toReject < 1) {
182-
return;
183-
}
184-
185-
$values[$i] = $val;
186-
187-
if (0 === --$toResolve) {
188-
$resolve($values);
189-
}
170+
$fulfiller = function ($val) use ($resolve): void {
171+
$resolve($val);
190172
};
191173

192-
$rejecter = function (\Throwable $reason) use ($i, &$reasons, &$toReject, $toResolve, $reject): void {
193-
if ($toResolve < 1 || $toReject < 1) {
194-
return;
195-
}
196-
174+
$rejecter = function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject): void {
197175
$reasons[$i] = $reason;
198176

199177
if (0 === --$toReject) {
200178
$reject(
201179
new CompositeException(
202180
$reasons,
203-
'Too many promises rejected.'
181+
'All promises rejected.'
204182
)
205183
);
206184
}
@@ -214,87 +192,6 @@ function some(array $promisesOrValues, int $howMany): PromiseInterface
214192
}, $cancellationQueue);
215193
}
216194

217-
/**
218-
* Traditional map function, similar to `array_map()`, but allows input to contain
219-
* promises and/or values, and `$mapFunc` may return either a value or a promise.
220-
*
221-
* The map function receives each item as argument, where item is a fully resolved
222-
* value of a promise or value in `$promisesOrValues`.
223-
*
224-
* @param array $promisesOrValues
225-
* @param callable $mapFunc
226-
* @return PromiseInterface
227-
*/
228-
function map(array $promisesOrValues, callable $mapFunc): PromiseInterface
229-
{
230-
if (!$promisesOrValues) {
231-
return resolve([]);
232-
}
233-
234-
$cancellationQueue = new Internal\CancellationQueue();
235-
236-
return new Promise(function ($resolve, $reject) use ($promisesOrValues, $mapFunc, $cancellationQueue): void {
237-
$toResolve = \count($promisesOrValues);
238-
$values = [];
239-
240-
foreach ($promisesOrValues as $i => $promiseOrValue) {
241-
$cancellationQueue->enqueue($promiseOrValue);
242-
$values[$i] = null;
243-
244-
resolve($promiseOrValue)
245-
->then($mapFunc)
246-
->done(
247-
function ($mapped) use ($i, &$values, &$toResolve, $resolve): void {
248-
$values[$i] = $mapped;
249-
250-
if (0 === --$toResolve) {
251-
$resolve($values);
252-
}
253-
},
254-
$reject
255-
);
256-
}
257-
}, $cancellationQueue);
258-
}
259-
260-
/**
261-
* Traditional reduce function, similar to `array_reduce()`, but input may contain
262-
* promises and/or values, and `$reduceFunc` may return either a value or a
263-
* promise, *and* `$initialValue` may be a promise or a value for the starting
264-
* value.
265-
*
266-
* @param array $promisesOrValues
267-
* @param callable $reduceFunc
268-
* @param mixed $initialValue
269-
* @return PromiseInterface
270-
*/
271-
function reduce(array $promisesOrValues, callable $reduceFunc, $initialValue = null): PromiseInterface
272-
{
273-
$cancellationQueue = new Internal\CancellationQueue();
274-
275-
return new Promise(function ($resolve, $reject) use ($promisesOrValues, $reduceFunc, $initialValue, $cancellationQueue): void {
276-
$total = \count($promisesOrValues);
277-
$i = 0;
278-
279-
$wrappedReduceFunc = function ($current, $val) use ($reduceFunc, $cancellationQueue, $total, &$i): PromiseInterface {
280-
$cancellationQueue->enqueue($val);
281-
282-
return $current
283-
->then(function ($c) use ($reduceFunc, $total, &$i, $val) {
284-
return resolve($val)
285-
->then(function ($value) use ($reduceFunc, $total, &$i, $c) {
286-
return $reduceFunc($c, $value, $i++, $total);
287-
});
288-
});
289-
};
290-
291-
$cancellationQueue->enqueue($initialValue);
292-
293-
\array_reduce($promisesOrValues, $wrappedReduceFunc, resolve($initialValue))
294-
->done($resolve, $reject);
295-
}, $cancellationQueue);
296-
}
297-
298195
/**
299196
* @internal
300197
*/

tests/FunctionAnyTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function shouldRejectWithAllRejectedInputValuesIfAllInputsAreRejected()
6161

6262
$compositeException = new CompositeException(
6363
[0 => $exception1, 1 => $exception2, 2 => $exception3],
64-
'Too many promises rejected.'
64+
'All promises rejected.'
6565
);
6666

6767
$mock = $this->createCallableMock();
@@ -126,6 +126,6 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfill
126126

127127
$promise2 = new Promise(function () {}, $this->expectCallableNever());
128128

129-
some([$deferred->promise(), $promise2], 1)->cancel();
129+
any([$deferred->promise(), $promise2], 1)->cancel();
130130
}
131131
}

0 commit comments

Comments
 (0)