Как заставить работать Guzzle асинхронно?

Есть вот такой запрос
$client = new Client();

        $promise = $client->requestAsync($method, 'https://api.sendgrid.com/v3' . $route, [
            RequestOptions::HEADERS => [
                'content-type' => 'application/json',
                'authorization' => 'Bearer ' . $this->key
            ],
            RequestOptions::BODY => json_encode($data)
        ]);

        $promise->then(
            static function (ResponseInterface $res) {
                \Yii::warning($res->getStatusCode());
            },
            static function (RequestException $e) {
                \Yii::warning($e->getMessage());
            }
        );


Но он работает, если юзать только с методом wait() который ждет завершение запроса.
Что не так я делаю?

Ошибок нет, просто requestAsync не отрабатывает
  • Вопрос задан
  • 1442 просмотра
Решения вопроса 1
Maksclub
@Maksclub Куратор тега PHP
maksfedorov.ru
Во время работы с Async Guzzle вам нужен вызов $curl->tick(), чтобы он мог продолжить работу. wait() под капотом делает именно это

Вот даже есть пример, как интегрировать курл с реакт-пхп и там есть этот тик, который делает движение
https://gist.github.com/psampaz/7f2aad5d1d54eeeec8...

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

$curl = new CurlMultiHandler;
$handler = HandlerStack::create($curl);
$client = new Client(['handler' => $handler]);

$p = $client
    ->getAsync('http://google.com')
    ->then(
        function (ResponseInterface $res) {
            echo 'response: ' . $res->getStatusCode() . PHP_EOL;
        },
        function (\Exception $e) {
            echo $e->getMessage() . PHP_EOL;
        }
    );

while ($p->getState() === 'pending') {
    $curl->tick();
    // sleep(1);
}
echo 'bottom' . PHP_EOL;


Если у вас синхронный фреймворк, то вам не пройти мимо синхронизации ожидания запроса. Профит в синхронном исполнении от асинхронных запросов есть только тогда, когда есть больше 1 запроса одновременно, тогда время выполнения станет равным самому длинному из запросов и это время придется ждать. Если запрос один — надо все равно прокрутить и дождаться...

Опишите изначальную задачу, которую преследуете

UPD после выяснения задачи:

Задача: рассылать почту, не задерживая клиента
Типовое решение: Выполнить fastcgi_finish_request и сделать после него отправку почты. То есть после выполнения данной функции идет разрыв с сервером, то есть браузер прогрузится до конца! Но сам скрипт еще поработает до того, как все сделает (и браузер об этом не узнает).

Можете сообщение записать в БД, а после fastcgi_finish_request всю очередь вычесать и отправить
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы