Maximieren Sie die asynchrone Leistung: Nutzen Sie die volle Leistung von Guzzle 7 über die ReactPHP-Ereignisschleife für nicht blockierende E/A
P粉043566314
P粉043566314 2024-02-17 14:29:49
0
1
512

Ich habe einen DiscordPHP-Bot und versuche, einige Webseiten herunterzuladen, die Cookies erfordern. Es scheint, dass ich den Curl-Handler mit Guzzle verwenden muss, da der ReactPHP-HTTP-Browser keine Cookies unterstützt.

Ich habe dieses minimale Skript erstellt:

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();

Dies wird sofort beendet, ohne dass der addPeriodicTimer 来检查挂起并手动调用 tick()-Code hinzugefügt wird:

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

Mit dem Timer funktioniert es wie erwartet:

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

Die Idee zur Verwendung tick() kam aus diesem geschlossenen Thread mit 73 Kommentaren auf github.com.

Es gibt einige ähnliche Fragen, aber keine scheint dieses Problem zu lösen:

  • Asynchrone Anfragen mit dem Guzzle 7-Proxy stellen, asynchrone Anfragen mit Guzzle senden, ohne auf Antwort zu warten, Guzzle-Pool anstelle von Guzzle-Versprechen verwenden und wie mehrere Anfragen gleichzeitig mit ReactPHP gesendet werden? Alle verwenden wait() Dies ist ein Sperranruf.
  • ReactPHP verspricht eine synchrone Ausführung mithilfe von sleep() 调用,ReactPHP 真的是异步的吗?执行一个长 for Schleifen. Beide blockieren die Schleife.
  • Bei parallelen Anfragen führen Guzzle, ReactPHP und Amphp sowie Guzzle und React Promise zu Endlosschleifen mit älteren Versionen von Guzzle oder veraltetem Code, der in Guzzle 7 nicht richtig funktioniert.

So verwenden Sie Cookie Jar, um HTTP GET zu initiieren und eine Antwort in der ReactPHP-Ereignisschleife zu erhalten, ohne blockierende Aufrufe (wie ->wait() oder manuelles Curling) zu verwenden GET 并在 ReactPHP 事件循环中获取响应,而不使用阻塞调用(例如 ->wait() 或手动 tick()

P粉043566314
P粉043566314

Antworte allen(1)
P粉384366923

嗯,ReactPHP 不会自动设置 cookie,已经有一个讨论此主题的票证: https ://github.com/reactphp/http/issues/445,但您仍然可以手动方式设置 HTTP cookie 标头。

还值得一提的是,将 ReactPHP 与 Guzzle 一起使用将不起作用,因为 Guzzle 会阻止 ReactPHP 的事件循环。这意味着您可以发送多个请求,但不能异步执行任何其他操作。

Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage