What methods are available for sending multiple requests concurrently in Guzzle?

Guzzle is a PHP HTTP client that simplifies making HTTP requests and integrates with web services. When working with multiple requests, especially if they are independent of each other, sending them concurrently can vastly improve performance by reducing the overall time waiting for responses.

Guzzle provides several methods to send requests concurrently:

1. Promises and Async Requests

Guzzle uses Promises from the Promises/A+ specification, allowing you to send asynchronous requests and use then() to handle responses once they're returned.

$promise = $client->getAsync('http://httpbin.org/get');
$promise->then(
    // On success
    function (ResponseInterface $res) {
        echo $res->getStatusCode() . "\n";
    },
    // On failure
    function (RequestException $e) {
        echo $e->getMessage() . "\n";
        echo $e->getRequest()->getMethod();
    }
);

2. Concurrent Requests with each()

The each() function allows you to handle multiple promises concurrently. You can control the concurrency level to limit the number of simultaneous requests.

$promises = [
    'image' => $client->getAsync('/image'),
    'png'   => $client->getAsync('/image.png'),
    'jpeg'  => $client->getAsync('/image.jpeg'),
    'webp'  => $client->getAsync('/image.webp')
];

$results = GuzzleHttp\Promise\settle($promises)->wait();

foreach ($results as $id => $result) {
    if (isset($result['value'])) {
        // Handle successful response
    } elseif (isset($result['reason'])) {
        // Handle exception
    }
}

3. Concurrent Requests with each_limit()

Similar to each(), each_limit() allows you to send multiple requests concurrently but limits the number of concurrent requests to avoid overwhelming the server or hitting rate limits.

$promises = (function () {
    yield $client->getAsync('/image');
    yield $client->getAsync('/image.png');
    yield $client->getAsync('/image.jpeg');
    // ...
})();

$pool = new GuzzleHttp\Pool($client, $promises, [
    'concurrency' => 5,
    'fulfilled' => function ($response, $index) {
        // this is delivered each successful response
    },
    'rejected' => function ($reason, $index) {
        // this is delivered each failed request
    },
]);

$promise = $pool->promise();
$promise->wait();

4. Guzzle Pool

The GuzzleHttp\Pool class provides the most control over concurrent requests. You can create a pool of requests and send them concurrently, handling the results as they come in.

$requests = function ($total) use ($client) {
    $uri = 'http://httpbin.org/get';
    for ($i = 0; $i < $total; $i++) {
        yield new \GuzzleHttp\Psr7\Request('GET', $uri);
    }
};

$pool = new \GuzzleHttp\Pool($client, $requests(100), [
    'concurrency' => 5,
    'fulfilled' => function ($response, $index) {
        // Handle success
    },
    'rejected' => function ($reason, $index) {
        // Handle rejection
    },
]);

$promise = $pool->promise();
$promise->wait();

These methods allow you to efficiently handle multiple HTTP requests in parallel, making your application faster and more responsive.

Remember to handle exceptions appropriately, especially when dealing with a large number of concurrent requests, as this increases the likelihood of encountering errors. It's also important to respect the terms of service and rate limits of the API or web service you are interacting with to avoid being blocked.

Related Questions

Get Started Now

WebScraping.AI provides rotating proxies, Chromium rendering and built-in HTML parser for web scraping
Icon