Параллельные HTTP-запросы через асинхронный API HttpClient
При интеграции с внешними сервисами часто требуется выполнить несколько HTTP-запросов. Последовательное выполнение приводит к суммированию времени ожидания каждого запроса. Если три API отвечают по 500мс, общее время составит 1.5 секунды. Класс Bitrix\Main\Web\HttpClient поддерживает асинхронное выполнение запросов через curl_multi, что позволяет выполнять их параллельно.
Для асинхронных запросов используется метод sendAsyncRequest(), который возвращает объект Promise. Promise реализует интерфейс Http\Promise\Promise и поддерживает цепочки обработчиков через метод then().
use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Web\Http\Request;
use Bitrix\Main\Web\Uri;
// Важно: для асинхронных запросов требуется CURL
$client = new HttpClient(['useCurl' => true]);
// Список URL для параллельных запросов
$urls = [
'products' => 'https://api.example.com/products',
'categories' => 'https://api.example.com/categories',
'prices' => 'https://api.example.com/prices',
];
$promises = [];
foreach ($urls as $key => $url)
{
// Создаём PSR-7 совместимый Request
$request = new Request('GET', new Uri($url));
// sendAsyncRequest() не блокирует выполнение
$promises[$key] = $client->sendAsyncRequest($request);
}
// wait() блокирует до завершения всех запросов
$responses = $client->wait();
// Обрабатываем результаты
foreach ($promises as $key => $promise)
{
try
{
// wait() на конкретном promise возвращает Response
$response = $promise->wait();
$data[$key] = json_decode((string)$response->getBody(), true);
}
catch (\Bitrix\Main\Web\Http\ClientException $e)
{
// Обработка ошибок сети
$data[$key] = ['error' => $e->getMessage()];
}
}
Promise поддерживает callback-функции для обработки успешных и неуспешных запросов:
$promise = $client->sendAsyncRequest($request);
// Регистрируем обработчики до вызова wait()
$promise->then(
function ($response) {
// Вызывается при успешном ответе
// Можно модифицировать и вернуть response
return $response;
},
function ($exception) {
// Вызывается при ошибке
// Логируем или обрабатываем исключение
return $exception;
}
);
// Запускаем выполнение
$client->wait();
Для POST-запросов с телом используйте Http\FormStream:
use Bitrix\Main\Web\Http\FormStream;
$body = new FormStream(['param1' => 'value1', 'param2' => 'value2']);
$request = new Request('POST', new Uri($url), ['Content-Type' => 'application/x-www-form-urlencoded'], $body);
$promise = $client->sendAsyncRequest($request);
Асинхронный API HttpClient использует curl_multi_exec() под капотом, что обеспечивает истинную параллельность на уровне сетевых операций. Три запроса по 500мс выполнятся примерно за 500мс вместо 1.5 секунд.
Похожие советы