#php #symfony #buffer
#php #symfony #буфер
Вопрос:
Я пытаюсь использовать StreamedResponse для вывода прогресса на мою индексную страницу в Symfony2.
Этот приведенный ниже код показывает мой прогресс в вызовах API по мере их возникновения, но у меня возникают проблемы с отображением потоковой информации в реальном представлении. Прямо сейчас он просто выводит обычный текст в верхней части страницы, а затем отображает представление, когда все завершено.
Я не хочу возвращать конечный массив и закрывать функцию, пока все не будет загружено, но, похоже, я не могу получить обычный шаблон twig для отображения во время вывода прогресса.
Я пытался использовать render, но, похоже, ничто не выводит этот файл просмотра на экран, если я не вернусь.
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'
. 'amp;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
);
}
Кроме того, еще одна важная деталь заключается в том, что я пытаюсь отобразить все в twig, и, похоже, с этим связаны некоторые интересные проблемы.
Комментарии:
1. Являются ли эти 15 запросов последовательными?
2. @Rhono, да, они последовательные. Прямо сейчас страница не отображается, пока все они не будут завершены, поэтому я пытаюсь показывать прогресс по мере завершения каждого вызова.
Ответ №1:
Насколько я понимаю, у вас есть только один шанс вывести что-то в браузер с сервера (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;
}
Ответ №2:
Вы можете реализовать всю логику в 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'
. 'amp;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;
}
Дальнейшее чтение этой и этой статьи.
Надеюсь, это поможет
Комментарии:
1. привет @absentx вы взглянули на этот ответ? о чем вы думаете?