【发布时间】:2021-10-03 18:57:08
【问题描述】:
我想用一个简单的例子来问这个问题。 (我会在文末写下)。
我读过这个: server sent events not updating until script is finished
但我不知道如何解决。
其答案 (https://stackoverflow.com/a/37690766/8494053) 的解决方案完美运行,所以可能是我的生产服务器中的缓存问题(共享虚拟主机)。
我在最后同时收到所有的 EventStream。
我已经检查了以下所有组合:
header('Cache-Control: no-cache, no-store, must-revalidate, private, max-age=0');
header('Pragma: no-cache');
header('Expires: 0');
但没有运气
任何人都知道如何在没有“str_pad($message, 800000)”的情况下解决这个问题?
有什么线索可以比较我的服务器的 localhost 配置和共享的 hostweb 服务器吗?
谢谢,
注意 1:两个环境中的 php 版本 8。我检查了我在共享网络服务器中使用 apached 作为开发环境和 CGI/FastCGI。有关系吗? 我发现了这个: Event Source -> Server returns event stream in bulk rather then returning in chunk
注意 2:两个服务器中的输出缓冲相同:output_buffering 4096
这是一个在我的主机中不起作用的简单示例:
test.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<br />
<input type="button" onclick="startTask();" value="Start Long Task" />
<input type="button" onclick="stopTask();" value="Stop Task" />
<br />
<br />
<p>Results</p>
<br />
<div id="results" style="border:1px solid #000; padding:10px; width:300px; height:250px; overflow:auto; background:#eee;"></div>
<br />
<progress id='progressor' value="0" max='100' ></progress>
<span id="percentage" style="text-align:right; display:block; margin-top:5px;">0</span>
</body>
</html>
<script>
var es;
function startTask() {
if (!!window.EventSource) {
es = new EventSource('long_process.php');
//a message is received
es.addEventListener('message', function(e) {
var result = JSON.parse( e.data );
addLog(result.message);
if(e.lastEventId == 'CLOSE') {
addLog('Received CLOSE closing');
es.close();
var pBar = document.getElementById('progressor');
pBar.value = pBar.max; //max out the progress bar
}
else {
var pBar = document.getElementById('progressor');
pBar.value = result.progress;
var perc = document.getElementById('percentage');
perc.innerHTML = result.progress + "%";
perc.style.width = (Math.floor(pBar.clientWidth * (result.progress/100)) + 15) + 'px';
}
});
es.addEventListener('error', function(e) {
addLog('Error occurred');
es.close();
});
}
}
function stopTask() {
es.close();
addLog('Interrupted');
}
function addLog(message) {
var r = document.getElementById('results');
r.innerHTML += message + '<br>';
r.scrollTop = r.scrollHeight;
}
</script>
long_process.php
<?php
header('Content-Type: text/event-stream');
// recommended to prevent caching of event data.
header('Cache-Control: no-cache');
function send_message($id, $message, $progress) {
$d = array('message' => $message , 'progress' => $progress);
echo "id: $id" . PHP_EOL;
echo "data: " . json_encode($d) . PHP_EOL;
echo PHP_EOL;
//push the data out by all force possible
ob_flush();
flush();
}
//LONG RUNNING TASK
for($i = 1; $i <= 10; $i++) {
send_message($i, 'on iteration ' . $i . ' of 10' , $i*10);
sleep(1);
}
send_message('CLOSE', 'Process complete', 100);
?>
关于@Tigger 答案的更新:我用过这段代码,但没有运气。我再次在脚本末尾(10 秒)连续收到所有信息,而不是每 1 秒收到一条消息。 (我还检查了“\n”和 PHP_EOL)。
function send_message($id, $message, $progress) {
$d = array('message' => $message , 'progress' => $progress);
echo "id: $id" . "\n";
echo "data: " . json_encode($d) . "\n";
echo "\n";
//push the data out by all force possible
while(ob_get_level() > 0) {
ob_end_flush();
}
flush();
}
更新关于第二个@Tigger 答案 我用过MDN sample on GitHub,但没有运气。 XAMPP 工作,我的生产网络服务器......没有。
关于托管服务提供商的更新 由于我没有找到解决方案,我已经联系了我的共享虚拟主机,这是他们的回答:
(用谷歌翻译):
您好,在分析案例后,我们已经能够验证,在像我们这样的平台上使用 SSE,在 apache 之前使用 nginx 代理,需要在托管的 nginx 配置中进行某些自定义,这使得与共享主机服务不兼容。您需要更可定制的服务,例如 vps 或虚拟专用服务器或类似服务。问候,
由于我无法更改 nginx 配置,我的 php 文件或 javascript 中是否有任何其他配置/命令可以帮助我?
【问题讨论】:
-
这台服务器可能只提供
fastCGI,而不提供CGI -
@Joseph 非常感谢您的回答,我如何查看您的要求?如果只是 fastCGI,我会找到解决方案吗?不是?只有当它是CGI?谢谢。
标签: javascript php server-sent-events event-stream