ReactPHP多API请求Promise无法正常resolve问题求助
解决ReactPHP中Guzzle异步请求与React\Promise\all()不resolve的问题
问题根源
Guzzle默认的异步请求使用自身的Promise实现,和ReactPHP的Promise体系不兼容,直接混用会导致React的Promise\all()无法正确追踪请求状态。而wait()是阻塞式等待Guzzle请求完成,相当于把异步转成同步执行,所以能工作,但完全违背了ReactPHP异步非阻塞的设计初衷。
解决方案
1. 使用Guzzle的ReactPHP适配器(推荐)
通过guzzlehttp/guzzle-react适配器,让Guzzle基于React事件循环执行异步请求,返回React兼容的Promise,从根源解决兼容性问题。
步骤:
- 安装依赖:
composer require guzzlehttp/guzzle guzzlehttp/guzzle-react react/event-loop
示例代码:
<?php require 'vendor/autoload.php'; use React\EventLoop\Factory; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Handler\CurlMultiHandler; use React\Promise\all; // 初始化React事件循环 $loop = Factory::create(); // 配置Guzzle使用React驱动的CurlMultiHandler $handler = new CurlMultiHandler(); $handler->setLoop($loop); $stack = HandlerStack::create($handler); $client = new Client(['handler' => $stack]); // 构建多个异步请求的Promise数组 $apiPromises = []; for ($i = 0; $i < 5; $i++) { $apiPromises[] = $client->getAsync("https://api.example.com/item/{$i}") ->then(function ($response) { // 解析响应结果,按需处理 return json_decode((string)$response->getBody(), true); }); } // 用React\Promise\all()批量处理所有请求 all($apiPromises) ->then(function ($allResults) { // 所有请求成功完成,处理结果集 foreach ($allResults as $idx => $result) { echo "请求 {$idx} 响应:" . print_r($result, true) . PHP_EOL; } }) ->otherwise(function ($error) { // 任意一个请求失败时触发 echo "请求错误:" . $error->getMessage() . PHP_EOL; }); // 启动事件循环,异步执行所有请求(必须调用,否则Promise不会触发) $loop->run();
2. 手动转换Guzzle Promise为React Promise
如果不想引入额外适配器,可手动将Guzzle的Promise包装成React兼容的Promise:
<?php require 'vendor/autoload.php'; use React\EventLoop\Factory; use React\Promise\Deferred; use GuzzleHttp\Client; use React\Promise\all; $loop = Factory::create(); $client = new Client(); $apiPromises = []; for ($i = 0; $i < 5; $i++) { $deferred = new Deferred(); // 发起Guzzle异步请求,绑定状态到React的Deferred $client->getAsync("https://api.example.com/item/{$i}") ->then( function ($response) use ($deferred) { $deferred->resolve(json_decode((string)$response->getBody(), true)); }, function ($error) use ($deferred) { $deferred->reject($error); } ); $apiPromises[] = $deferred->promise(); } // 批量处理Promise all($apiPromises) ->then(function ($allResults) { foreach ($allResults as $idx => $result) { echo "请求 {$idx} 响应:" . print_r($result, true) . PHP_EOL; } }) ->otherwise(function ($error) { echo "请求错误:" . $error->getMessage() . PHP_EOL; }); $loop->run();
3. 关键注意事项
- 必须启动React事件循环:所有ReactPHP异步操作依赖事件循环,最后一定要调用
$loop->run(),否则Promise永远不会触发resolve/reject。 - 禁止使用
wait():wait()会阻塞事件循环,完全破坏异步非阻塞的特性,仅用于调试或同步场景。 - 统一Promise体系:确保所有传入
React\Promise\all()的Promise都属于React的Promise体系,避免不同实现混用。
内容的提问来源于stack exchange,提问作者Philipp Braun
相关产品推荐
相关产品推荐

