php實現Promise.all和Promise.race

效果

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章