skip to Main Content

Does not work: I am trying to run multiple HTTP requests concurrently using Laravel’s HTTP facade.
Unfortunately, Laravel always executes them in sequence when I am using Http::async()->get(...):

use IlluminateSupportFacadesHttp;
use GuzzleHttpPromiseUtils;

$promises = [
    Http::async()->get('https://postman-echo.com/delay/3'),
    Http::async()->get('https://postman-echo.com/delay/3'),
];
$combinedPromise = Utils::all($promises);
$results = $combinedPromise->wait();

Works: If I am using Laravel’s pool API instead the requests are executed concurrently as expected:

use IlluminateSupportFacadesHttp;
use IlluminateHttpClientPool;

$responses = Http::pool(fn(Pool $pool) => [
    $pool->get('https://postman-echo.com/delay/3'),
    $pool->get('https://postman-echo.com/delay/3'),
]);

Works: Also, using GuzzleHttp directly I am able to execute the requests concurrently:

use GuzzleHttpClient;
use GuzzleHttpPromiseUtils;

$client = new Client([
    'base_uri' => 'https://postman-echo.com'
]);
$promises = [
    $client->getAsync('/delay/3'),
    $client->getAsync('/delay/3'),
];
$combinedPromise = Utils::all($promises);
$results = $combinedPromise->wait();

Versions used: I tested it with "laravel/framework": "9.47.0" and "laravel/framework": "10.14.1" in combination with PHP 8.2.1.

Question: Does anyone know why my Http::async()->get(...) calls are not executed concurrently but in sequence?

2

Answers


  1. Chosen as BEST ANSWER

    Thanks to @txyoji who pointed me to the correct Laravel code I was able to find a solution that works with Laravel 9 and 10:

    use IlluminateSupportFacadesHttp;
    use GuzzleHttpPromiseUtils;
    
    $client = Http::async();
    $client = $client->setClient(new Client([
        'handler' => $client->buildHandlerStack(),
        'cookies' => true,
    ]));
    
    $promises = [
        $client->get('https://postman-echo.com/delay/3'),
        $client->get('https://postman-echo.com/delay/3'),
    ];
    $combinedPromise = Utils::all($promises);
    
    $results = $combinedPromise->wait();
    

    Since Laravel 9 PendingRequest.buildClient() no longer calls PendingRequest.getReusableClient() to reuse the same GuzzleHttp Client across async requests.

    The code above explicitly sets a GuzzleHttp Client that is then reused across the async requests.


  2. Docs show using pool to accomplish this.

    The Http facade returns a IlluminateHttpClientPendingRequest object.

    If PendingRequest async() is true, it doesn’t reuse the client.
    My guess is each call of the Http facade is providing a separate client object.

    Use the same client and it should work.

    $client = Http::async();
    $promises = [
        $client->get('https://postman-echo.com/delay/3'),
        $client->get('https://postman-echo.com/delay/3'),
    ];
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search