我有一個 DiscordPHP 機器人,我正在嘗試下載一些需要 cookie 的網頁。看來我需要將curl處理程序與Guzzle一起使用,因為ReactPHP http瀏覽器不支援cookie。
我創建了這個最小的腳本:
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();
這會立即退出,而無需添加 addPeriodicTimer
來檢查掛起並手動呼叫 tick()
的程式碼:
$ time php minimal.php 0.022u 0.010s 0:00.03 100.0% 0+0k 0+0io 67pf+0w
使用計時器,它按預期工作:
Tick Beat Tick Beat Tick Beat Tick Beat Tick Beat Tick Beat Tick response: 200 Beat Beat Beat ...
使用 tick()
的想法來自 github.com 上的這個 73 條評論的封閉線程。
有一些類似的問題,但似乎都沒有解決這個問題:
wait()
這是一個阻塞呼叫。 sleep()
調用,ReactPHP 真的是異步的嗎?執行一個長 for
迴圈。兩者都阻塞了循環。 如何使用cookie jar 啟動HTTP GET
並在ReactPHP 事件循環中取得回應,而不使用阻塞呼叫(例如->wait()
或手動tick()
ing curl 的處理程序?强>
嗯,ReactPHP 不會自動設定cookie,已經有一個討論此主題的票證:https ://github.com/reactphp/http/issues/445,但您仍然可以手動設定HTTP cookie 標頭。
也值得一提的是,將 ReactPHP 與 Guzzle 一起使用將不起作用,因為 Guzzle 會阻止 ReactPHP 的事件循環。這意味著您可以發送多個請求,但不能非同步執行任何其他操作。