我正在尝试使用streamedResponse将进度输出到Symfony2中的索引页面。
下面的代码确实显示了我在api调用时的进度,但是我在实际视图中渲染流信息时遇到了问题。现在它只是在页面顶部输出纯文本,然后在全部完成时渲染视图。
我不想返回最后一个数组并关闭函数,直到所有内容都被加载,但是在输出进度时我似乎无法显示常规的twig模板。
我尝试使用渲染但似乎没有任何东西真正将视图文件输出到屏幕,除非我返回。
public function indexAction($countryCode)
{
//anywhere from five to fifteen api calls are going to take place
foreach ($Widgets as $Widget) {
$response = new StreamedResponse();
$curlerUrl = $Widget->getApiUrl()
. '?action=returnWidgets'
. '&data=' . urlencode(serialize(array(
'countryCode' => $countryCode
)));
$requestStartTime = microtime(true);
$curler = $this->get('curler')->curlAUrl($curlerUrl);
$curlResult = json_decode($curler['body'], true);
if(isset($curlResult['data'])){
//do some processing on the data
}
$response->setCallback(function() use ($Widget, $executionTime) {
flush();
sleep(1);
var_dump($Widget->getName());
var_dump($executionTime);
flush();
});
$response->send();
}
//rest of indexAction with a return statement
return array(
//all the vars my template will need
);
}
此外,另一个重要的细节是,我正在努力渲染所有的树枝,似乎有一些有趣的问题。
答案 0 :(得分:0)
据我了解,您只有一次机会从服务器(PHP / Twig)向浏览器输出内容,然后由JavaScript进行任何进一步更改(如更新进度条)。
我建议使用multi-cURL异步执行所有15个请求。这有效地使总请求时间等于最慢的请求,因此您可以更快地提供页面,并且可以消除对进度条的需要。
// Create the multiple cURL handle
$mh = curl_multi_init();
$handles = array();
$responses = array();
// Create and add the cURL handles to the $mh
foreach($widgets as $widget) {
$ch = $curler->getHandle($widget->getURL()); // Code that returns a cURL handle
$handles[] = $ch;
curl_multi_add_handle($mh, $ch);
}
// Execute the requests
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running > 0);
// Get the request content
foreach($handles as $handle) {
$responses[] = curl_multi_getcontent($handle);
// Close the handles
curl_close($handle);
}
curl_multi_close();
// Do something with the responses
// ...
理想情况下,这是Curler
服务的一种方法。
public function processHandles(array $widgets)
{
// most of the above
return $responses;
}
答案 1 :(得分:0)
您可以实现setCallback
方法中的所有逻辑,因此请考虑以下代码:
public function indexAction($countryCode)
{
$Widgets = [];
$response = new StreamedResponse();
$curlerService = $this->get('curler');
$response->setCallback(function() use ($Widgets, $curlerService, $countryCode) {
foreach ($Widgets as $Widget) {
$curlerUrl = $Widget->getApiUrl()
. '?action=returnWidgets'
. '&data=' . urlencode(serialize(array(
'countryCode' => $countryCode
)));
$requestStartTime = microtime(true);
$curler = $curlerService->curlAUrl($curlerUrl);
$curlResult = json_decode($curler['body'], true);
if(isset($curlResult['data'])){
//do some processing on the data
}
flush();
sleep(1);
var_dump($Widget->getName());
var_dump( (microtime(true) - $requestStartTime) );
flush();
}
});
// Directly return the streamed response object
return $response;
}
希望这个帮助