PHP使用生成器封装GuzzleHttp\Pool响应时返回null报错如何解决
问题根因
\GuzzleHttp\Pool的promise()->wait()默认返回值为null,不会自动聚合所有请求的响应结果,因此你尝试遍历null就触发了foreach参数类型错误。
另外你最初版本的代码没有实现真正的并发:每次发起异步请求后立刻调用wait(),会阻塞等待当前请求返回后才发起下一个请求,本质还是同步串行请求。
修正方案
需要在Pool的配置参数中添加fulfilled回调主动收集成功的响应结果,同时可添加rejected回调处理请求异常场景,等所有请求执行完成后遍历自己收集的结果数组即可。
修正后的可运行代码如下:
function prepare_requests(int $total): \Generator { for ($i = 0; $i < $total; $i++) { $uri = "https://httpbin.org/anything?q=$i"; yield new \GuzzleHttp\Psr7\Request('GET', $uri); } } function do_pool_requests(\GuzzleHttp\Client $client, int $total): \Generator { // 自定义数组存储请求结果 $results = []; $pool = new \GuzzleHttp\Pool($client, prepare_requests($total), [ 'concurrency' => 25, // 成功回调,收集响应 'fulfilled' => function (\GuzzleHttp\Psr7\Response $response, $index) use (&$results) { $results[$index] = [ 'headers' => $response->getHeaders(), 'response' => $response->getBody()->getContents() ]; }, // 失败回调,可自定义错误处理 'rejected' => function (\GuzzleHttp\Exception\RequestException $e, $index) use (&$results) { $results[$index] = [ 'error' => $e->getMessage() ]; } ]); // wait()执行完成后,所有结果已经存入$results数组 $pool->promise()->wait(); // 按请求顺序返回结果 ksort($results); foreach ($results as $item) { yield $item; } } $client = new \GuzzleHttp\Client(); foreach (do_pool_requests($client, 100) as $do_request) { var_dump($do_request); }
补充说明
- 回调中的
$index参数对应请求生成的顺序,处理完成后用ksort排序可以保证返回结果和你发起请求的顺序一致 - 并发参数
concurrency的配置已经生效,会严格控制最多同时发起25个请求
内容的提问来源于stack exchange,提问作者VBobCat
相关产品推荐
相关产品推荐

