Search code examples
phpasynchronousreactphp

How to can I write php asynchroneous functions using reactphp


I thought I can do more at same time so I started with reactphp. The code runs so fine, but I wanted to be sure that the code was indeed asynchroneous I tried the code below which gave me no confidence, it echoed the strings 'in natural order' like "one two three four..." but I was looking for output like "one four three two..." just as it happens in javascript.

function callDone(){
    $g = 'abcdefghuytegbnwsgwseeveddvvdvdcvdvbshasfcfddbbcdgcdvoiuyyttreewwaazxcvbnjjjhgfffhhhabcdefghuytegbnwsgwseeveddvvdvdcvdvbshasfcfddbbcdgcdvoiuyyttreewwaazxcvbnjjjhgfffhhh';
    $r = str_split($g);
    for($i=0;$i<count($r);$i++){
        $g .= $r[$i];
    }
    return 1;
}
$promise = new React\Promise\Promise(function($resolve){
    echo microtime(true). "<br>start<br>";
    $resolve(callDone());
}
$promise->then(function($v){
    echo 'one<br>';
});
$promise->then(function($v){
    echo 'two<br>';
});
$promise->then(function($v){
    echo 'three<br>';
});
$promise->then(function($v){
    echo 'four<br>';
});
$promise->then(function($v){
    echo 'five<br>';
});

this will print "one two three four five" But I needed something out of order like: "one three two..." to confirm this is really asynchroneous. Any help thanks in advance.


Solution

  • The problem with the your example is the expectation that these calls should be some kind randomized. The asynchronous aspect of ReactPHP comes mostly from the event-loop which must be non-blocking(as you mentioned in one of the comments below). Not using the event-loop means you are using the standard call stack of PHP.

    If you want to see an "more asynchronous" approach you could modify your code a bit.

    $loop = \React\EventLoop\Factory::create();
    
    function callDone(){
        $g = 'abcdefghuytegbnwsgwseeveddvvdvdcvdvbshasfcfddbbcdgcdvoiuyyttreewwaazxcvbnjjjhgfffhhhabcdefghuytegbnwsgwseeveddvvdvdcvdvbshasfcfddbbcdgcdvoiuyyttreewwaazxcvbnjjjhgfffhhh';
        $r = str_split($g);
        for($i=0;$i<count($r);$i++){
            $g .= $r[$i];
        }
        return 1;
    }
    $promise = new React\Promise\Promise(function($resolve){
        echo microtime(true). "<br>start<br>";
        $resolve(callDone());
    });
    
    $promise->then(function($v) use ($loop) {
        $loop->addPeriodicTimer(0.1, function () {
            echo 'one<br>';
        });
    });
    
    $promise->then(function($v) use ($loop) {
        $loop->addPeriodicTimer(0.2, function () {
            echo 'two<br>';
        });
    });
    $promise->then(function($v){
        echo 'three<br>';
    });
    $promise->then(function($v){
        echo 'four<br>';
    });
    $promise->then(function($v){
        echo 'five<br>';
    });
    
    $loop->run();
    

    We added the event-loop to your code to start a more asynchronous approach. This will add an asynchronous time to your example which will echo "one" every 0.1 seconds and "two" every 0.2 seconds. As you may see these two timers won't block each other because the event-loop handles these timers. I hope this helps!