mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-19 09:26:45 +00:00
Add Promise::all
(#6152)
This commit is contained in:
parent
20837c9894
commit
6bb84bc46c
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\promise;
|
||||
|
||||
use function count;
|
||||
use function spl_object_id;
|
||||
|
||||
/**
|
||||
@ -57,4 +58,53 @@ final class Promise{
|
||||
//rejected or just hasn't been resolved yet
|
||||
return $this->shared->state === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise that will resolve only once all the Promises in
|
||||
* `$promises` have resolved. The resolution value of the returned promise
|
||||
* will be an array containing the resolution values of each Promises in
|
||||
* `$promises` indexed by the respective Promises' array keys.
|
||||
*
|
||||
* @param Promise[] $promises
|
||||
*
|
||||
* @phpstan-template TPromiseValue
|
||||
* @phpstan-template TKey of array-key
|
||||
* @phpstan-param non-empty-array<TKey, Promise<TPromiseValue>> $promises
|
||||
*
|
||||
* @phpstan-return Promise<array<TKey, TPromiseValue>>
|
||||
*/
|
||||
public static function all(array $promises) : Promise{
|
||||
if(count($promises) === 0){
|
||||
throw new \InvalidArgumentException("At least one promise must be provided");
|
||||
}
|
||||
/** @phpstan-var PromiseResolver<array<TKey, TPromiseValue>> $resolver */
|
||||
$resolver = new PromiseResolver();
|
||||
$values = [];
|
||||
$toResolve = count($promises);
|
||||
$continue = true;
|
||||
|
||||
foreach($promises as $key => $promise){
|
||||
$promise->onCompletion(
|
||||
function(mixed $value) use ($resolver, $key, $toResolve, &$values) : void{
|
||||
$values[$key] = $value;
|
||||
|
||||
if(count($values) === $toResolve){
|
||||
$resolver->resolve($values);
|
||||
}
|
||||
},
|
||||
function() use ($resolver, &$continue) : void{
|
||||
if($continue){
|
||||
$continue = false;
|
||||
$resolver->reject();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if(!$continue){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $resolver->getPromise();
|
||||
}
|
||||
}
|
||||
|
@ -35,3 +35,18 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/world/generator/normal/Normal.php
|
||||
|
||||
-
|
||||
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertFalse\\(\\) with false will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../phpunit/promise/PromiseTest.php
|
||||
|
||||
-
|
||||
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertTrue\\(\\) with false and 'All promise should…' will always evaluate to false\\.$#"
|
||||
count: 1
|
||||
path: ../../phpunit/promise/PromiseTest.php
|
||||
|
||||
-
|
||||
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertTrue\\(\\) with false will always evaluate to false\\.$#"
|
||||
count: 2
|
||||
path: ../../phpunit/promise/PromiseTest.php
|
||||
|
||||
|
@ -39,4 +39,110 @@ final class PromiseTest extends TestCase{
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function testAllPreResolved() : void{
|
||||
$resolver = new PromiseResolver();
|
||||
$resolver->resolve(1);
|
||||
|
||||
$allPromise = Promise::all([$resolver->getPromise()]);
|
||||
$done = false;
|
||||
$allPromise->onCompletion(
|
||||
function($value) use (&$done) : void{
|
||||
$done = true;
|
||||
self::assertEquals([1], $value);
|
||||
},
|
||||
function() use (&$done) : void{
|
||||
$done = true;
|
||||
self::fail("Promise was rejected");
|
||||
}
|
||||
);
|
||||
self::assertTrue($done);
|
||||
}
|
||||
|
||||
public function testAllPostResolved() : void{
|
||||
$resolver = new PromiseResolver();
|
||||
|
||||
$allPromise = Promise::all([$resolver->getPromise()]);
|
||||
$done = false;
|
||||
$allPromise->onCompletion(
|
||||
function($value) use (&$done) : void{
|
||||
$done = true;
|
||||
self::assertEquals([1], $value);
|
||||
},
|
||||
function() use (&$done) : void{
|
||||
$done = true;
|
||||
self::fail("Promise was rejected");
|
||||
}
|
||||
);
|
||||
self::assertFalse($done);
|
||||
$resolver->resolve(1);
|
||||
self::assertTrue($done);
|
||||
}
|
||||
|
||||
public function testAllResolve() : void{
|
||||
$resolver1 = new PromiseResolver();
|
||||
$resolver2 = new PromiseResolver();
|
||||
|
||||
$allPromise = Promise::all([$resolver1->getPromise(), $resolver2->getPromise()]);
|
||||
$done = false;
|
||||
$allPromise->onCompletion(
|
||||
function($value) use (&$done) : void{
|
||||
$done = true;
|
||||
self::assertEquals([1, 2], $value);
|
||||
},
|
||||
function() use (&$done) : void{
|
||||
$done = true;
|
||||
self::fail("Promise was rejected");
|
||||
}
|
||||
);
|
||||
self::assertFalse($done);
|
||||
$resolver1->resolve(1);
|
||||
self::assertFalse($done);
|
||||
$resolver2->resolve(2);
|
||||
self::assertTrue($done);
|
||||
}
|
||||
|
||||
public function testAllPartialReject() : void{
|
||||
$resolver1 = new PromiseResolver();
|
||||
$resolver2 = new PromiseResolver();
|
||||
|
||||
$allPromise = Promise::all([$resolver1->getPromise(), $resolver2->getPromise()]);
|
||||
$done = false;
|
||||
$allPromise->onCompletion(
|
||||
function($value) use (&$done) : void{
|
||||
$done = true;
|
||||
self::fail("Promise was unexpectedly resolved");
|
||||
},
|
||||
function() use (&$done) : void{
|
||||
$done = true;
|
||||
}
|
||||
);
|
||||
self::assertFalse($done);
|
||||
$resolver2->reject();
|
||||
self::assertTrue($done, "All promise should be rejected immediately after the first constituent rejection");
|
||||
$resolver1->resolve(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Promise::all() should return a rejected promise if any of the input promises were rejected at the call time
|
||||
*/
|
||||
public function testAllPartialPreReject() : void{
|
||||
$resolver1 = new PromiseResolver();
|
||||
$resolver2 = new PromiseResolver();
|
||||
$resolver2->reject();
|
||||
|
||||
$allPromise = Promise::all([$resolver1->getPromise(), $resolver2->getPromise()]);
|
||||
$done = false;
|
||||
$allPromise->onCompletion(
|
||||
function($value) use (&$done) : void{
|
||||
$done = true;
|
||||
self::fail("Promise was unexpectedly resolved");
|
||||
},
|
||||
function() use (&$done) : void{
|
||||
$done = true;
|
||||
}
|
||||
);
|
||||
self::assertTrue($done, "All promise should be rejected immediately after the first constituent rejection");
|
||||
$resolver1->resolve(1);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user