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();}
相关文章
相关标签/搜索