react\http\browser 是 reactphp 提供的非阻塞异步 http 客户端,基于事件循环实现单进程并发,需显式运行 $loop->run(),适用于 cli 或长连接场景,不适用于同步框架的常规请求生命周期。

ReactPHP 的 React\Http\Browser 是最直接的异步 HTTP 客户端
PHP 原生 cURL 或 file_get_contents() 都是阻塞的,而 ReactPHP 提供了真正非阻塞的 HTTP 请求能力。核心是 React\Http\Browser ——它基于事件循环,不依赖多线程或多进程,单进程即可并发发请求。
使用前确保已安装:composer require react/http-client(注意:新版 ReactPHP 已将客户端移至 react/http 包,实际应装 react/http,但客户端类仍在 React\Http\Browser)。
- 必须显式运行事件循环:
$loop->run(),否则请求永远不会发出 - 不能在同步框架(如 Laravel、Symfony)的常规 HTTP 请求生命周期里直接用——会卡住整个响应;适合 CLI 场景或长连接服务(如 WebSocket 后端)
-
Browser默认不处理重定向,需手动判断301/302并重新发起请求 - 超时需通过
timeout选项控制,例如['timeout' => 5.0],否则可能无限等待
发多个请求时别用 await,要用 Promise\all() 并行
ReactPHP 基于 Promise,不是 async/await(PHP 8.1+ 的 async 关键字也不适用于 ReactPHP)。常见错误是写成串行等待:
// ❌ 错误:这仍是阻塞式写法(且语法不合法)
$result1 = await $browser->get('https://api.a');
$result2 = await $browser->get('https://api.b'); // 等完第一个才发第二个
正确做法是构造 Promise 数组,用 React\Promise\all() 并发触发:
立即学习“PHP免费学习笔记(深入)”;
$promises = [
$browser->get('https://api.a'),
$browser->get('https://api.b'),
$browser->post('https://api.c', ['json' => ['x' => 1]])
];
React\Promise\all($promises)->then(function ($responses) {
// 所有响应同时到达,按顺序对应 $promises 中的请求
echo $responses[0]->getBody() . "\n";
});
$loop->run(); // 必须启动循环
- 每个
$browser->xxx()返回的是PromiseInterface,不是结果本身 - 不要在
then()回调里再发新请求却不返回 Promise——会导致链断裂,后续无法 catch - 若某请求失败,
all()会 reject,可用React\Promise\settle()改为“全部完成,不管成败”
遇到 Call to a member function then() on null 多半是没传 $loop
ReactPHP 组件高度依赖事件循环实例。漏传或传错 $loop,会导致内部资源未初始化,Browser 构造失败却静默返回 null,之后调用 then() 就崩了。
检查点:
- 是否用
React\EventLoop\Factory::create()显式创建了循环? - 是否把该循环实例传给了
new Browser($loop)? - 是否在
Browser实例化后、调用请求前,修改或销毁了$loop? - 是否在 Composer 自动加载未生效时,手动
require了文件却没触发 autoloader?
最小可运行示例必须包含这三块:创建 loop → 创建 browser → 发请求 + then() → $loop->run()。
HTTP/2、连接复用、DNS 缓存这些得靠底层驱动,PHP 默认不支持
ReactPHP 的 HTTP 客户端默认走纯 PHP 实现的 TCP 连接,不自动启用 HTTP/2,也不共享连接池。这意味着:
- 每个请求都新建 TCP 连接(除非手动复用
Connector),开销比 Guzzle + cURL 高 - DNS 查询每次都会发生,无内置缓存;高频请求建议配合
React\Dns\Resolver\Resolver使用自定义解析器 - 若目标服务强制 HTTP/2(如某些云 API),
Browser会降级到 HTTP/1.1,可能被拒绝或限流 - 上传大文件时,记得用
stream而非一次性读入内存,避免 OOM
真正需要高性能、高兼容性的异步调用,ReactPHP 更适合作为底层通信模块嵌入守护进程;若只是偶尔异步拉数据,Guzzle + curl_multi 可能更稳、更省心。











