javascript — сервер отправлял события, не обновляющиеся, пока скрипт не завершится

У меня есть небольшой скрипт, который обновляет базу данных. В настоящее время процесс обработки занимает около минуты, но время увеличивается с ростом базы данных. Я хочу предоставить пользователю обновления во время выполнения сценария, чтобы они знали, что состояние сценария и что он все еще выполняется. Я реализовал Server-Side-Events, и пока он работает, ни одно из обновлений не публикуется на веб-сайте, пока сценарий не будет полностью завершен.

Я могу загрузить весь файл скрипта, но вот соответствующие части.

Во-первых, в начале скрипта я проверяю, запускается ли скрипт из командной строки, и если нет, я отправляю заголовки, как показано:

$cli = (PHP_SAPI === 'cli') ? 1 : 0;
if(!$cli){
header( 'Content-Type: text/event-stream' );
header( 'Cache-Control: no-cache' );
}

Вот моя функция для отправки sse_message при вызове

function sse_message( $type, $message, $progress=0 )
{
$d = array("type" => $type, "msg" => $message , "progress" => $progress);
$id = time();

echo "id: $id" . PHP_EOL;
echo "data: " . json_encode($d) . PHP_EOL;
echo PHP_EOL;

ob_flush();
flush();
}

И, наконец, вот моя реализация javascript для слушателя:

if( typeof(EventSource) !== "undefined" ){
source = new EventSource( "../priv3/script/prowip_process.php" );
source.addEventListener("message", function(e)
{
var result = JSON.parse(e.data);

switch(result.type){
case "update":
if( result.msg != "" )
document.getElementById("prowip_status").value += "\n[INFO]: "+result.msg;
document.getElementById("prowip_progress").value = result.progress;
break;

case "success":
document.getElementById("prowip_status").value += "\n[COMPLETED]:"+result.msg;
document.getElementById("prowip_progress").value = 100;
document.getElementById("button_prowip_exit").disabled = false;
source.close();
break;

case "error":
document.getElementById("prowip_status").value += "\n[ERROR]: "+result.msg;
document.getElementById("button_prowip_exit").disabled = false;
source.close();
break;
}
}, false);
}
else{
document.getElementById("prowip_status").value += "\n\n[ERROR]: Your browser does not support server-sent events.  Please upgrade your browser or use a different browser for this function.  Please note this script will not work with Internet Explorer."document.getElementById("button_prowip_exit").disabled = false;
}

Опять же — все работает отлично, за исключением того, что во время процесса сценария не происходит никаких обновлений, а затем, когда он заканчивается, все сообщения и индикатор выполнения обновляются.

Я пробовал это в нескольких браузерах, компьютерах и т. Д., Но ни одно из обновлений веб-страницы не происходит, пока не будет выполнен весь сценарий.

Любая помощь или комментарии будут с благодарностью. Благодарю.

ИЗДАН 3/3/2015, ЧТОБЫ ПОСТАВИТЬ БОЛЬШЕ КОДА ПО ЗАПРОСУ

Эти 3 функции вызывают sse_message или просто echo для CLI.

function show_error( $cli, $message )
{
if ($cli)
echo $message."\n";
else
sse_message( "error", $message );
}

function show_message( $cli, $message, $progress )
{
if ($cli)
echo $message."[".$progress."%]\n";
else
sse_message( "update", $message, $progress );
}

function show_success( $cli, $message )
{
if ($cli)
echo $message."[100%]\n";
else
sse_message( "success", $message );
}

Вот клип из основной функции, который показывает, как эти функции вызываются:

foreach ( $projects as $number => $project ) {
$cn = strtok($number, "." );
$pn = strtok(".");
$wipover = $project['wip'] - $project['wip30'] - $project['wip60'] - $project['wip90'];
$arover = $project['ar'] - $project['ar30'] - $project['ar60'] - $project['ar90'];
$process_counter++;
if( $process_counter >= $check ){
$progress+=5;
$check += intval ( $counter / 16 );
show_message($cli,"",$progress);
}
if( ($project['empty']==1) and ($project['wip']==0) and ($project['ar']==0) ){
//Do nothing...
}
else{
$write_counter++;
$update_query = "update projects set wip='{$project['wip']}', wip30='{$project['wip30']}', wip60='{$project['wip60']}', wip90='{$project['wip90']}', wipover='$wipover', ar='{$project['ar']}', ar30='{$project['ar30']}', ar60='{$project['ar60']}', ar90='{$project['ar90']}', arover='$arover' where client_num='$cn' and new_num='$pn'";
if( ! $db->query( $update_query ) ){
show_error( $cli, "ERROR - update query: [$update_query] returned error: [".$db->error."]", $progress );
}
}
}

2

Решение

Я была такая же проблема. Оказалось, что веб-сервер кеширует вывод php.

В PHP ob_flush () и flush () форсируют вывод PHP на веб-сервер, но не могут заставить веб-сервер отправить его клиенту.

Мое решение состояло в том, чтобы заполнить вывод до 800 000 символов перед сбросом из PHP. то есть:

echo "data: " . str_pad($message, 800000) . PHP_EOL . PHP_EOL;

Каждый ответ клиенту имеет размер около 6 КБ, поэтому он не очень эффективен, но это был единственный способ заставить его работать.

Надеюсь, это поможет!

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]