2014-01-20 54 views
1

我實現了長輪詢機制使用XMLHttprequest。我的問題是,瀏覽器關閉後,服務器端進程繼續運行,不關閉。XmlHttpRequest不終止請求處理

該web服務器是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腳本(阿帕奇有「php_value output_buffering關」):

<?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

什麼是你到目前爲止的代碼? – everton

+0

我添加了代碼,發現php必須嘗試將數據輸出回客戶端以發現連接已被中止 –

+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) . ';'; 
    } 
}