我使用 XMLHttprequest 实现了长轮询机制。我的问题是,在浏览器关闭后,服务器端进程继续运行并且不会关闭。
网络服务器是 httpd apache ,该过程是 php 脚本。
我确实希望在浏览器关闭后关闭php脚本。
我发现php没有发现连接关闭,除非它试图将数据输出回浏览器。 这是一个问题,因为它会影响最小化带宽使用的目标。
客户端脚本,使用onreadystatechange尝试读取部分数据,而不需要为每次通信使用新的XMLHttprequest。 在整个响应完成之前,某些浏览器不允许读取部分数据:
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"></meta>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(NewReq);
var mode = 0;
function NewReq() {
var Req = new XMLHttpRequest();
var url = 'a.php';
if (mode) {
url += '?mode=' + mode;
}
Req.open('GET', url);
Req.onreadystatechange = function(event) {
var handler = ReadyState[this.readyState];
if (typeof handler == 'function') {
handler(this);
}
};
inc_mycookie();
Req.send();
}
var ReadyState = [
//'NotInit', 'ReqRec', 'ConEst'
null , null, null,
partial // 'Proccessing'
,
complete //'Finishied'
];
function partial(Req) { //'Proc'
if (mode == 1) {
return;
}
try {
var strings = Req.response.split(';');
strings.pop();
var data = JSON.parse(strings.pop());
$('#message').text(data);
mode = 2;
}
catch (e) {
$('#message').text(e.message);
mode = 1;
}
return;
}
function complete(Req) {
var last = $('#message').text();
$('#output').text(last);
NewReq();
}
function inc_mycookie() {
var matches = document.cookie.match(/(?:^|;)mine=([^;]+);?/);
if (matches) {
var inc = parseInt(matches[1]) + 1;
document.cookie = 'mine=' + inc;
}
}
</script>
</head>
<body>
<h3> output </h3>
<div id="output"></div>
<h3> partial </h3>
<div id="message"></div>
</body>
</html>
这里是php脚本(apache有“php_value output_buffering Off”):
<?php
header('Content-type: application/json');
if (!isset($_COOKIE['mine'])) {
setcookie('mine', 23);
$_COOKIE['mine'] = 23;
}
$mode = isset($_GET['mode']) ? $_GET['mode'] : 1;
print json_encode('test_' . $_COOKIE['mine']) . ';';
if ($mode == 2 ) {
$iter = 8;
while($iter) {
sleep(2);
$iter--;
error_log('a.php:' . $iter);
// if i remove this line, then erro_log will continue to show even when browser is closed
print json_encode('test_' . $_COOKIE['mine'] . '_' . $iter) . ';';
}
}
?>
在浏览器支持部分响应的情况下,损坏也不算太差。
但是如果浏览器要求完成整个响应,则损坏将是长轮询的完全妥协,这意味着每5秒重复一次请求。
答案 0 :(得分:0)
一种可能的解决方案是添加间隔:
<?php
$iter = 200;
while($iter) {
sleep(2);
$iter--;
error_log('a.php:' . $iter);
if (update_exist()) {
print json_encode('test_' . $_COOKIE['mine'] . '_' . $iter) . ';';
}
else if (($iter-200)%20 == 0) { // 180, 160, 140 ... 40, 20, 0
print json_encode('check connection : ' . $iter) . ';';
}
}
答案 1 :(得分:0)
即使已经快5岁了,请考虑
XMLHTTPRequest.abort()
问题中的javascript需要通过以下方式重新设计:
Req
设为全局变量,这样Req.abort()
中调用window.addEventListener('unload', function() { Req.abort(); })
以使关闭页面可能导致客户端终止与服务器的连接。