Ajax異步請求PHP服務器,如何作到無阻塞響應 原創 學習與分享 PHP自學

最近發現了一個ajax異步請求的問題,用$.post、$.get、$.ajax請求PHP服務器時,老是沒法異步返回數據。

經屢次測試才發現:
-- 不一樣瀏覽器,請求不一樣域名-不阻塞:無需實驗
-- 不一樣瀏覽器,請求同域名-不阻塞:session_id()返回不一樣
-- 同一瀏覽器,請求不一樣域名-不阻塞:session_id返回不一樣
-- 同一瀏覽器,請求同域名-阻塞:session_id()返回相同

發現問題所在:
1 關閉XDEBUG
2 SESSION鎖
3 清除輸出緩衝區

1 關閉XDEBUG
XDEBUG是實時調試。調試時,它將保持FPM以確保線程正在工做以免數據污染。 
典型的測試方法是,使用XDEBUG進行調試時,打開另外一個瀏覽器並訪問該站點,該站點這個時候是沒法訪問的。 
這對並行響應有重大影響,即,即便前端發送多個請求,它也受XDEBUG控制,而且只能同時響應一個。 
另外,因爲XDEBUG依賴於SESSION,所以即便您使用session_write_close(),也要關閉會話鎖(請參見下文)。 
XDEBUG仍會自動打開。

2 SESSION鎖
用 session_write_close() 關閉SESSION的寫鎖,這適合SESSION保存爲File的狀況。
若是SESSION保存在Redis,則不須要。

3 清除輸出緩衝區
使用session_write_close()可能沒法當即關閉SESSION鎖,因此在這個方法以前加上:ob_end_flush()。
讓 session_write_close() 立刻生效。


圖片
4 示例
有以下一個範例,當點擊【提交】按鈕時,前端會給後臺服務器發送兩種請求。
一種是get請求,每隔1秒請求一次。
一種是post請求,最開始的時候發送一次,而後等待相應結束。

看看HTML代碼
javascript

<form>
<input type="submit" value="提交" />
</form>

<script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>

<script type="text/javascript">
    $('form').on('submit'function(e{
        e.preventDefault();

        // 每隔一秒請求一次服務器
        var id = setInterval(function({
            $.get(
                'save.php?action=get',
                {},
                function(data{
                    console.log(data);
                },
                'json'
            );
        }, 1000);

        $.post(
            'save.php?action=post',
            {},
            function(data{
                console.log(data);
                // 中止定時循環
                clearInterval(id);
            },
            'json'
        );
    });
</script>


php代碼
php

<?php

session_start();

$action = $_GET['action'];

if ($action == 'post') {

   $_SESSION['time'] = 0;
   session_write_close();

    while ($_SESSION['time'] < 5) {
      session_start();
      $_SESSION['time'] = $_SESSION['time'] + 1;

      // 將SESSION數據寫入文件中,並關閉寫鎖
      session_write_close();

      // sleep()模擬花費時間較長的程序,這樣在關閉寫鎖以後,
      // 服務器就可以相應別的請求,以下的$action=get,
      sleep(1);
    }

    echo json_encode([session_id() => $_SESSION['time']]);
    exit();
}

if ($action == 'get') {
    echo json_encode([session_id() => $_SESSION['time']]);
    exit();}
相關文章
相關標籤/搜索