在现代前端开发中,JavaScript 的 Promise.all 是处理多个异步请求并发执行的利器。它可以让多个请求同时发起,等待所有请求完成后再执行后续逻辑。PHP 作为服务器端语言,虽然没有直接的 Promise 机制,但通过 curl_multi 系列函数,我们同样可以实现类似的并发请求处理。本文重点讲解如何使用 curl_multi_info_read 来实现类似 Promise.all 的并发请求处理。
普通的 curl_exec 是同步的,也就是说每次请求都得等待结果返回后才能继续执行下一步。如果有多个请求要发,顺序执行效率非常低。curl_multi 允许我们同时发起多个请求,然后并发处理,提高性能。
创建多个独立的 cURL 句柄(curl_init)。
将这些句柄加入到一个 curl_multi 句柄中。
使用 curl_multi_exec 循环执行所有请求。
通过 curl_multi_info_read 获取已经完成的请求信息。
关闭完成的句柄,并保存结果。
等待所有请求完成,类似于 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 并发请求有所帮助!