效果
#php promise.php
array(2) {
[1]=>
string(3) "two"
[0]=>
string(3) "one"
}
string(3) "two"
object(Exception)#15 (7) {
...
}
代碼
<?php
declare(strict_types=1);
use Swow\Coroutine;
use Swow\Channel;
use Swow\Selector;
use Swow\Sync\WaitGroup;
$promise1 = function () {
msleep(500);
return 'one';
};
$promise2 = function () {
msleep(100);
return 'two';
};
$promise3 = function () {
msleep(50);
throw new \Exception('Reject');
};
var_dump(promise_all([$promise1, $promise2]));
var_dump(promise_race([$promise1, $promise2]));
var_dump(promise_race([$promise1, $promise2, $promise3]));
/**
* @param array $callbacks
* @param int $parallel 併發數量
* @return array
*/
function promise_all(array $callbacks, int $parallel = -1)
{
$wg = new WaitGroup();
$channel = new Channel($parallel);
$results = [];
foreach ($callbacks as $key => $callback) {
$channel->push(true);
$wg->add();
Coroutine::run(static function () use ($wg, $channel, $callback, $key, &$results) {
try {
$results[$key] = $callback();
} catch (\Throwable) {
} finally {
$channel->pop();
$wg->done();
}
});
}
$wg->wait();
return $results;
}
/**
* @param array $callbacks
* @param int $timeout 超時
* @param bool $throw 是否拋出異常
* @return mixed
*/
function promise_race(array $callbacks, int $timeout = -1, bool $throw = true)
{
$selector = new Selector();
foreach ($callbacks as $callback) {
$channel = new Channel();
Coroutine::run(static function () use ($channel, $callback) {
try {
$channel->push($callback());
} catch (\Throwable $e) {
$channel->push($e);
}
});
$selector->pop($channel);
}
try {
$selector->commit($timeout);
return $selector->fetch();
} catch (\Throwable $e) {
if ($throw) {
throw $e;
}
}
return false;
}