Menu

Reference / Async

awaitAny()

function
function awaitAny(Task ...$tasks): mixed

Wait for the first successful task and return its value.

A failure is ignored while another task can still succeed. If every task failed, AggregateError is thrown with the errors keyed by input position. The other tasks are not cancelled; they keep running under their own scope. A failure that happened before the winner finished is ignored; a loser still running when the winner is returned is released from this call, so if it fails later the error is escalated to its owning scope like any unclaimed failure. Cancel the losers yourself when you no longer need them.

Parameters

...$tasks Task
the tasks to wait for; at least one

Returns

mixed — the value of the first task to succeed

Throws

AggregateError
when every task failed
\LogicException
when called with no tasks

Example

use Async\AggregateError;
use function Async\async;
use function Async\awaitAny;
use function Async\delay;
use function Async\spawn;

async(function () {
    // A failure is ignored while another task can still succeed.
    $fails = spawn(function () { delay(0.01); throw new RuntimeException("mirror 1 down"); });
    $wins = spawn(function () { delay(0.02); return "mirror 2"; });
    echo awaitAny($fails, $wins), "\n";

    // Only when every task failed does awaitAny() throw.
    $x = spawn(function () { throw new RuntimeException("first"); });
    $y = spawn(function () { delay(0.01); throw new RuntimeException("second"); });
    try {
        awaitAny($x, $y);
    } catch (AggregateError $e) {
        foreach ($e->errors() as $i => $err) {
            echo "task $i: ", $err->getMessage(), "\n";
        }
    }
});

Output

mirror 2
task 0: first
task 1: second

See also: awaitAll

View source