gpt4 book ai didi

javascript - 服务器发送的事件在脚本完成之前不会更新

转载 作者:行者123 更新时间:2023-11-30 00:31:09 24 4
gpt4 key购买 nike

我有一个更新数据库的小脚本。目前处理大约需要一分钟左右,但随着数据库的增加,时间会增加。我想在脚本运行时向用户提供更新,以便他们知道脚本的状态并且它仍在运行。我实现了 Server-Side-Events 并且在它工作时,在脚本完全完成之前不会将任何更新发布到网站。

我可以上传整个脚本文件,但这里是相关部分。

首先,在脚本开始时,我检查脚本是否从命令行运行,如果不是,我发送 header ,如下所示:

$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;
}

同样 - 一切都完美无缺,除了在脚本过程中没有发生任何更新,然后在它完成所有消息和进度条时更新。

我已经在多个浏览器、计算机等中尝试过此操作,但在整个脚本完成之前,不会对网页进行任何更新。

如有任何帮助或意见,我们将不胜感激。谢谢。

2015 年 4 月 3 日编辑以根据要求发布更多代码

这 3 个函数调用 sse_message 或只是为 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 );
}

这是 main 函数的一个片段,显示了如何调用这些函数:

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 );
}
}
}

最佳答案

我遇到了同样的问题。原来是 web 服务器缓存了 php 的输出。

在 PHP 中,ob_flush() 和 flush() 强制输出从 PHP 到 Web 服务器,但不能强制 Web 服务器将其推送到客户端。

我的解决方案是在从 PHP 刷新之前将输出填充到 800,000 个字符。即:

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

返回给客户端的每个响应大约有 6Kb 大,因此效率不是很高,但这是我让它工作的唯一方法。

希望对您有所帮助!

关于javascript - 服务器发送的事件在脚本完成之前不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29446659/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com