当前位置: 首页> 最新文章列表> 如何用 curl_multi_info_read 实现类似 JavaScript 中 Promise.all 的并发请求处理?

如何用 curl_multi_info_read 实现类似 JavaScript 中 Promise.all 的并发请求处理?

M66 2025-06-15

在现代前端开发中,JavaScript 的 Promise.all 是处理多个异步请求并发执行的利器。它可以让多个请求同时发起,等待所有请求完成后再执行后续逻辑。PHP 作为服务器端语言,虽然没有直接的 Promise 机制,但通过 curl_multi 系列函数,我们同样可以实现类似的并发请求处理。本文重点讲解如何使用 curl_multi_info_read 来实现类似 Promise.all 的并发请求处理。


为什么要用 curl_multi?

普通的 curl_exec 是同步的,也就是说每次请求都得等待结果返回后才能继续执行下一步。如果有多个请求要发,顺序执行效率非常低。curl_multi 允许我们同时发起多个请求,然后并发处理,提高性能。


基本思路

  1. 创建多个独立的 cURL 句柄(curl_init)。

  2. 将这些句柄加入到一个 curl_multi 句柄中。

  3. 使用 curl_multi_exec 循环执行所有请求。

  4. 通过 curl_multi_info_read 获取已经完成的请求信息。

  5. 关闭完成的句柄,并保存结果。

  6. 等待所有请求完成,类似于 Promise.all 等待所有 Promise 完成。


代码示例

以下示例代码展示如何并发请求多个 URL,并在所有请求完成后统一处理返回结果。示例中的 URL 域名都替换为 m66.net

<?php
// 要请求的URL列表
$urls = [
    'https://m66.net/api/user',
    'https://m66.net/api/order',
    'https://m66.net/api/product',
];

// 初始化 curl_multi 句柄
$mh = curl_multi_init();
$handles = [];

// 初始化所有请求句柄并加入 multi 句柄
foreach ($urls as $key => $url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    // 设置超时等其他选项根据需求调整
    curl_multi_add_handle($mh, $ch);
    $handles[$key] = $ch;
}

// 执行所有请求
$running = null;
do {
    curl_multi_exec($mh, $running);
    // 等待活动连接,有效减少CPU使用率
    curl_multi_select($mh);
    
    // 读取完成的请求
    while ($info = curl_multi_info_read($mh)) {
        if ($info['msg'] == CURLMSG_DONE) {
            // 找出完成请求的句柄
            $finishedHandle = $info['handle'];
            // 找出对应的 key
            $key = array_search($finishedHandle, $handles, true);
            
            // 获取内容和状态码
            $content = curl_multi_getcontent($finishedHandle);
            $httpCode = curl_getinfo($finishedHandle, CURLINFO_HTTP_CODE);
            
            echo "请求 {$urls[$key]} 完成,HTTP状态码: {$httpCode}\n";
            echo "内容长度: " . strlen($content) . " 字节\n\n";
            
            // 关闭并移除已经完成的句柄
            curl_multi_remove_handle($mh, $finishedHandle);
            curl_close($finishedHandle);
            
            // 将对应句柄置空,方便后续判断
            unset($handles[$key]);
        }
    }
} while ($running > 0);

curl_multi_close($mh);

echo "所有请求均已完成。\n";

代码解析

  • curl_multi_init() 创建一个多请求处理的句柄。

  • 每个 curl_init() 创建一个单独请求,配置后加入多请求句柄。

  • 通过 curl_multi_exec() 启动请求,循环调用直到所有请求完成。

  • 使用 curl_multi_select() 防止 CPU 占用过高。

  • curl_multi_info_read() 返回已经完成的请求信息,类似于 Promise 的 then 回调。

  • 请求完成后,及时关闭和移除对应句柄,避免资源浪费。

  • 通过以上流程,实现了所有请求并发,完成后统一处理,效果类似 Promise.all


总结

虽然 PHP 没有原生的 Promise 机制,但利用 curl_multi 系列函数,特别是 curl_multi_info_read,完全可以实现并发请求的管理和结果处理。借助这种方式,可以大幅提升 PHP 脚本执行多接口调用时的效率,特别适合需要同时调用多个外部接口的场景。

希望本文示例对你理解 PHP 并发请求有所帮助!