XmlHttpRequest不会终止请求处理

时间:2014-01-20 21:07:40

标签: php apache xmlhttprequest

我使用 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秒重复一次请求。

2 个答案:

答案 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需要通过以下方式重新设计:

  1. Req设为全局变量,这样
  2. 例如,可以在
  3. Req.abort()中调用
  4. window.addEventListener('unload', function() { Req.abort(); })

以使关闭页面可能导致客户端终止与服务器的连接。

相关问题