我正在尝试使用服务器发送的事件创建连接,在生成所有消息后立即获取所有消息,而不是等到脚本结束。为此,我只通过使用 ob_implicit_flush 和 ob_flush 找到了解决方案,但是,通过使用它,我无法在浏览器网络监视器中不导致 NS_ERROR_ABORT 错误的情况下正确关闭连接。
虽然它按原样工作,但在脚本完成时会产生错误。当我使用常规 flush() 时,它可以工作并且不会发生 NS_ERROR_ABORT 错误,但是消息不会在生成后立即发送,而是在 PHP 脚本末尾发送。
PHP代码是这样的:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
ob_implicit_flush(true);
echo "data: Connection established\n\n";
ob_flush();
sleep(3); // Code will be here, that may be take some time. It will print messages too.
echo "data: Script End\n\n";
ob_flush();
echo "event: close\n";
echo "data: END\n\n";
ob_flush();
fclose();
?>
在 PHP 上发送关闭事件以使用 JavaScript 捕获它并关闭连接。 (睡眠功能只是为了模拟延迟)。
JavaScript代码是这样的:
let source = null;
function initSSE() {
if (source === null) {
source = new EventSource('test.php');
source.onmessage = function(event) {
console.log('Message:', event.data);
};
source.onerror = function(error) {
console.error('Connection error:', error);
source.close();
source = null;
};
source.addEventListener('close', function(event) {
console.log('Connection closed');
source.close();
source = null;
});
}
}
initSSE();
删除常规 flush() 的 ob_flush() 并删除 ob_implicit_flush(true) 修复问题。代码只执行一次,没有重新连接,也没有 NS_ERROR_ABORT,但消息是在 PHP 脚本的末尾发送的。我读到服务器上的压缩可能导致 flush() 无法立即工作,所以我尝试通过多种方式设置“SetEnv no-gzip 1”来禁用 .htaccess 上服务器的 gzip,但没有任何反应。我也试过 ini_set('zlib.output_compression', '0');在 PHP 代码上。
还在 PHP 脚本上尝试了 ignore_user_abort,并将 fclose() 更改为 exit();
还有另一种方法可以中间获取 SSE 消息,或者修复此代码?我不喜欢忽略那个错误,但是如果忽略那个错误就可以了?