How to obtain concurrently in PHP using ReactPHP

150 views Asked by At

I want to process multiple process in same time. I searched and found that this can be happen using the ReactPHP. I tried but could not successes. I added the Time of each process start/end time and results showed that each function's start time is not same. I want that starttime of each function should be same.

Here is my code

<?php
require 'vendor/autoload.php';
use React\EventLoop\Factory;
use React\Promise\Promise;

$loop = Factory::create();

function asyncTask($taskName)
{
    return new Promise(function ($resolve) use ($taskName) {
        $startTime = (int)microtime(true);
        echo "Starting $taskName at " . date('Y-m-d H:i:s', $startTime) . "\n";

        $loop = React\EventLoop\Factory::create();
        $loop->addTimer(rand(1, 5), function () use ($resolve, $taskName, $startTime) {
            $endTime = (int)microtime(true);
            echo "Completed $taskName at " . date('Y-m-d H:i:s', $endTime) . "\n";

            $resolve([
                'taskName' => $taskName,
                'startTime' => $startTime,
                'endTime' => $endTime,
            ]);
        });

        $loop->run();
    });
}

$promises = [
    'Task 1' => asyncTask('Task 1'),
    'Task 2' => asyncTask('Task 2'),
    'Task 3' => asyncTask('Task 3'),
];

\React\Promise\all($promises)->then(function ($results) {
    echo "All tasks completed: <br>";
    foreach ($results as $result) {
        echo "{$result['taskName']} started at " . date('Y-m-d H:i:s', $result['startTime']) . " and ended at " . date('Y-m-d H:i:s', $result['endTime']) . "\n";
    }
});

$loop->run();
?>

and results are showing below as
Starting Task 1 at 2024-01-18 17:37:09
Completed Task 1 at 2024-01-18 17:37:10
Starting Task 2 at 2024-01-18 17:37:10
Completed Task 2 at 2024-01-18 17:37:14
Starting Task 3 at 2024-01-18 17:37:14
Completed Task 3 at 2024-01-18 17:37:15
All tasks completed:
Task 1 started at 2024-01-18 17:37:09 and ended at 2024-01-18 17:37:10
Task 2 started at 2024-01-18 17:37:10 and ended at 2024-01-18 17:37:14
Task 3 started at 2024-01-18 17:37:14 and ended at 2024-01-18 17:37:15

and I want to see each task's starting time as 2024-01-18 17:37:09

1

There are 1 answers

4
WyriHaximus On

ReactPHP core developer here.

A few things, first of we changed the way the event loop is used so that you only have to call Loop::addTimer in your case.

Secondly, you're creating a new event loop once at the top of your file, and then in every function call, so 4 times.

As pointed out by Sammitch, you are still doing all of this in one thread. So unless you want to start using ext-parallel or react/child-process you will still do everything in the same single core process. Unless you are doing CPU bound operations that single process won't be an issue. If you are doing CPU bound operations, child process can help you out.

With our async package, you can write your code the following:

<?php

use React\EventLoop\Loop;
use React\Promise\Promise;

use function React\Async\async;
use function React\Async\await;
use function React\Promise\all;
use function React\Promise\Timer\sleep;

require 'vendor/autoload.php';

/**
 * @return array<string, float>
 */
function asyncTask($taskName): array
{
    $startTime = (int)microtime(true);
    echo "Starting $taskName at " . date('Y-m-d H:i:s', $startTime) . "\n";

    await(sleep(random_int(1, 5)));

    $endTime = (int)microtime(true);
    echo "Completed $taskName at " . date('Y-m-d H:i:s', $endTime) . "\n";
    return [
        'taskName' => $taskName,
        'startTime' => $startTime,
         'endTime' => $endTime,
    ];
}

$promises = [
    'Task 1' => async(static fn () => asyncTask('Task 1'))(),
    'Task 2' => async(static fn () => asyncTask('Task 2'))(),
    'Task 3' => async(static fn () => asyncTask('Task 3'))(),
];

$results = await(all($promises));

echo 'All tasks completed:', PHP_EOL;
foreach ($results as $result) {
   echo "{$result['taskName']} started at ", date('Y-m-d H:i:s', $result['startTime']), ' and ended at ', date('Y-m-d H:i:s', $result['endTime']), PHP_EOL;
}