Current Location: Home> Latest Articles> How to Achieve Concurrent Request Handling Like JavaScript's Promise.all with curl_multi_info_read

How to Achieve Concurrent Request Handling Like JavaScript's Promise.all with curl_multi_info_read

M66 2025-06-15

In modern frontend development, JavaScript's Promise.all is a powerful tool for handling concurrent asynchronous requests. It allows multiple requests to be initiated simultaneously, and only executes subsequent logic once all requests have completed. Although PHP, as a server-side language, does not have a native Promise mechanism, we can achieve similar concurrent request handling using the curl_multi series of functions. This article will explain how to use curl_multi_info_read to implement concurrent request handling similar to Promise.all.


Why Use curl_multi?

Regular curl_exec is synchronous, meaning each request must wait for the result before moving on to the next one. If there are multiple requests to make, executing them sequentially is inefficient. curl_multi allows us to send multiple requests simultaneously and handle them concurrently, thus improving performance.


Basic Approach

  1. Create multiple independent cURL handles (curl_init).

  2. Add these handles to a curl_multi handle.

  3. Use curl_multi_exec to execute all requests in a loop.

  4. Use curl_multi_info_read to retrieve the information of the completed requests.

  5. Close the completed handles and save the results.

  6. Wait for all requests to finish, similar to Promise.all waiting for all Promises to resolve.


Code Example

The following sample code demonstrates how to make concurrent requests to multiple URLs and process the results once all requests have completed. In the example, all the URLs have been replaced with m66.net.

<?php
// List of URLs to request
$urls = [
    'https://m66.net/api/user',
    'https://m66.net/api/order',
    'https://m66.net/api/product',
];
<p>// Initialize the curl_multi handle<br>
$mh = curl_multi_init();<br>
$handles = [];</p>
<p>// Initialize all request handles and add them to the multi handle<br>
foreach ($urls as $key => $url) {<br>
$ch = curl_init();<br>
curl_setopt($ch, CURLOPT_URL, $url);<br>
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);<br>
// Set other options like timeouts as needed<br>
curl_multi_add_handle($mh, $ch);<br>
$handles[$key] = $ch;<br>
}</p>
<p>// Execute all requests<br>
$running = null;<br>
do {<br>
curl_multi_exec($mh, $running);<br>
// Wait for active connections to reduce CPU usage<br>
curl_multi_select($mh);</p>
while ($info = curl_multi_info_read($mh)) {
    if ($info['msg'] == CURLMSG_DONE) {
        // Identify the handle of the completed request
        $finishedHandle = $info['handle'];
        // Find the corresponding key
        $key = array_search($finishedHandle, $handles, true);
        
        // Get the content and HTTP status code
        $content = curl_multi_getcontent($finishedHandle);
        $httpCode = curl_getinfo($finishedHandle, CURLINFO_HTTP_CODE);
        
        echo "Request to {$urls[$key]} completed, HTTP Status Code: {$httpCode}\n";
        echo "Content Length: " . strlen($content) . " bytes\n\n";
        
        // Close and remove the completed handle
        curl_multi_remove_handle($mh, $finishedHandle);
        curl_close($finishedHandle);
        
        // Set the corresponding handle to null for later checks
        unset($handles[$key]);
    }
}

} while ($running > 0);

curl_multi_close($mh);

echo "All requests have been completed.\n";


Code Explanation

  • curl_multi_init() creates a handle for multi-request processing.

  • Each curl_init() creates an individual request, which is then configured and added to the multi-request handle.

  • The curl_multi_exec() function initiates the requests and runs in a loop until all requests are completed.

  • curl_multi_select() is used to prevent excessive CPU usage.

  • curl_multi_info_read() returns the information of completed requests, similar to the then callback of a Promise.

  • After a request is completed, the corresponding handle is closed and removed to avoid resource wastage.

  • This approach allows all requests to run concurrently and process the results once they are all finished, effectively mimicking the behavior of Promise.all.


Conclusion

Although PHP does not have a native Promise mechanism, using the curl_multi series of functions, especially curl_multi_info_read, allows us to effectively manage concurrent requests and handle their results. This approach can significantly improve the performance of PHP scripts when making multiple API calls, especially in scenarios where several external APIs need to be called simultaneously.

We hope this example helps you understand PHP concurrent request handling!