我需要使用Guzzle检查数据库中的很多项目.例如,项目数量为2000-5000.将其全部加载到单个数组中太多了,因此我想将其分成多个块:SELECT * FROM items LIMIT100.当最后一个项目发送到Guzzle时,则请求下一个100个项目.在“已满”处理程序中,我应该知道哪个项目得到了响应.我看到这里有$index,它指向当前项目的数量.但是我无法访问$items变量可见的范围.无论如何,如果我什至可以通过use($items)访问它,那么在循环的第二遍中,我会得到错误的索引,因为$items数组中的索引将从0开始,而$index则大于100.因此,此方法将不起作用.
$client = new Client();
$iterator = function() {
while($items = getSomeItemsFromDb(100)) {
foreach($items as $item) {
echo "Start item #{$item['id']}";
yield new Request('GET', $item['url']);
}
}
};
$pool = new Pool($client, $iterator(), [
'concurrency' => 20,
'fulfilled' => function (ResponseInterface $response, $index) {
// how to get $item['id'] here?
},
'rejected' => function (RequestException $reason, $index) {
call_user_func($this->error_handler, $reason, $index);
}
]);
$promise = $pool->promise();
$promise->wait();
我想我能做些什么
$request = new Request('GET', $item['url']);
$request->item = $item;
然后在“已实现”的处理程序中只是为了从$response获取$request-这将是理想的.但正如我所看到的那样,没有办法做类似$response-> getRequest()的事情.
关于如何解决这个问题的任何建议?
解决方法:
不幸的是,在Guzzle中不可能收到请求.有关更多详细信息,请参见响应创建.
但是,您可以返回一个不同的Promise,并使用each_limit()代替Pool(内部,pool类只是对EachPromise的包装).这是更通用的解决方案,可与任何类型的诺言一起使用.
另外看看another example of EachPromise usage for concurrent HTTP request.
$client = new Client();
$iterator = function () use ($client) {
while ($items = getSomeItemsFromDb(100)) {
foreach ($items as $item) {
echo "Start item #{$item['id']}";
yield $client
->sendAsync(new Request('GET', $item['url']))
->then(function (ResponseInterface $response) use ($item) {
return [$item['id'], $response];
});
}
}
};
$promise = \GuzzleHttp\Promise\each_limit(
$iterator(),
20,
function ($result, $index) {
list($itemId, $response) = $result;
// ...
},
function (RequestException $reason, $index) {
call_user_func($this->error_handler, $reason, $index);
}
);
$promise->wait();