Maximize asynchronous performance: Unleash the full power of Guzzle 7 via the ReactPHP event loop for non-blocking I/O
P粉043566314
P粉043566314 2024-02-17 14:29:49
0
1
461

I have a DiscordPHP bot and I'm trying to download some web pages that require cookies. It seems that I need to use curl handler with Guzzle because ReactPHP http browser does not support cookies.

I created this minimal script:

use GuzzleHttp\Client;
use GuzzleHttp\Handler\CurlMultiHandler;
use GuzzleHttp\HandlerStack;
use Psr\Http\Message\ResponseInterface;

include 'vendor/autoload.php';

$loop = \React\EventLoop\Loop::get();

$curl = new CurlMultiHandler;
$handler = HandlerStack::create($curl);
$client = new Client( [ /* 'cookies' => $cookieJar, */ 'handler' => $handler ] );

$promise = $client->getAsync('https://httpstat.us/200')
    ->then(
        function (ResponseInterface $res) {
            echo 'response: ' . $res->getStatusCode() . PHP_EOL;
        },
        function (\Exception $e) {
            echo $e->getMessage() . PHP_EOL;
        }
    );


$timer = $loop->addPeriodicTimer(0.5, function () use ($curl, $promise) {
    if ($promise->getState() === 'pending') {
    echo 'Tick ';
    $curl->tick();
    }
    echo 'Beat ';
});

$loop->run();

This will exit immediately without adding addPeriodicTimer to check for hangs and manually calling tick():

$ time php minimal.php
0.022u 0.010s 0:00.03 100.0%    0+0k 0+0io 67pf+0w

Using a timer, it works as expected:

Tick Beat Tick Beat Tick Beat Tick Beat Tick Beat Tick Beat Tick response: 200
Beat Beat Beat ...

The idea to use tick() came from this 73-comment closed thread on github.com.

There are some similar questions, but none seem to solve this problem:

  • Using Guzzle 7 proxy for asynchronous requests, using Guzzle to send asynchronous requests without waiting for response, using Guzzle pool instead of guzzle promises and how to send multiple requests at once ReactPHP? Use all wait() This is a blocking call.
  • ReactPHP promises synchronous execution using sleep() calls, is ReactPHP really asynchronous? Execute a long for loop. Both block the loop.
  • For parallel requests, Guzzle, ReactPHP and Amphp, and Guzzle and React Promise can lead to infinite loops using older versions of Guzzle or deprecated code that does not work properly in Guzzle 7.

How to use cookie jar to initiate HTTP GET and get the response in the ReactPHP event loop without using blocking calls (such as ->wait() or manuallytick()ing curl handler?

P粉043566314
P粉043566314

reply all(1)
P粉384366923

Well, ReactPHP does not set cookies automatically, there is already a ticket discussing this topic: https://github.com/reactphp/http/issues/445, but you can still set it manually HTTP cookie header.

It’s also worth mentioning that using ReactPHP with Guzzle won’t work because Guzzle blocks ReactPHP’s event loop. This means you can send multiple requests, but you can't do anything else asynchronously.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!