PHP 提前响应客户端及后续处理

hyx 2019-03-20 09:28:34 247次 0

处理web端页面的时候,往往会遇到一个问题,就是 ajax 请求 php 代码后,由于 php 代码执行时间过长,导致页面等待响应时间过长,此时我们可以想办法让 php 提前返回响应,然后再继续执行其他处理。

方法

  • fastcgi_finish_request,官方解释:此函数冲刷(flush)所有响应的数据给客户端并结束请求。 这使得客户端结束连接后,需要大量时间运行的任务能够继续运行。
  • register_shutdown_function,官方解释:注册一个 callback ,它会在脚本执行完成或者 exit() 后被调用。
  • __destruct,官方解释:析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。

测试代码

index.html

<html>
    <head>
        <title>PHP TEST</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
        <script src="../jquery.js"></script>
        <script>
            function getCurrentTime(d) {
                var time = d.getFullYear() + "-" +(d.getMonth()+1) + "-" + d.getDate() + " " + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds();
                return time;
            }
            function check() {
                $.ajax({
                    url: 'success.php',
                    success:function(data){
                        console.log(data);
                        console.log(getCurrentTime(new Date()));
                    }
                });
            }
            function requestA() {
                $.ajax({
                    url: 'fastcgi_finish_request.php',
                    success:function(data){
                        console.log(data);
                        console.log(getCurrentTime(new Date()));
                        check()
                    }
                });
            }
            function requestB() {
                $.ajax({
                    url: 'register_shutdown_function.php',
                    success:function(data){
                        console.log(data);
                        console.log(getCurrentTime(new Date()));
                        check()
                    }
                });
            }
            function requestC() {
                $.ajax({
                    url: 'destruct.php',
                    success:function(data){
                        console.log(data);
                        console.log(getCurrentTime(new Date()));
                        check()
                    }
                });
            }
        </script>
        <a href="#" onclick="requestA();">请求 fastcgi_finish_request.php</a><br/>
        <a href="#" onclick="requestB();">请求 register_shutdown_function.php</a><br/>
        <a href="#" onclick="requestC();">请求 destruct.php</a><br/>
    </body>
</html>


success.php

<?php
//用于确定第二次请求
echo 'success';


fastcgi_finish_request.php

<?php
if(!function_exists('fastcgi_finish_request')) {
    //若不是php-fpm模式,则使用如下代码代替
    ob_end_flush();
    ob_start();
}
echo 'request fastcgi_finish_request. sleep 5s';
if(!function_exists('fastcgi_finish_request')) {
    function fastcgi_finish_request() {
        //若不是php-fpm模式,则使用如下代码代替
        ob_flush();
        flush();
    }
}
fastcgi_finish_request();
//执行其他函数
sleep(5);


register_shutdown_function.php

<?php
//注册函数
$echo = function(){
    sleep(5);
};
echo 'request register_shutdown_function. sleep 5s';
register_shutdown_function($echo);

destruct.php

<?php
class Test {
    public function __construct(){
    }
    public function result() {
        return 'request destruce. sleep 5s';
    }
    public function __destruct() {
        sleep(5);
    }
}
$test = new Test();
echo $test->result();


测试结果

  • fastcgi_finish_request 函数结果
    fastcgi_finish_request 函数结果

  • register_shutdown_function 函数结果
    register_shutdown_function 函数结果

  • __destruct 函数结果

__destruct 函数结果

结果分析

从上面执行图片可以看出,每个然后都可以实现此功能,这样基本需求是可以实现的;如果有更深层次的需求,需要对比几个函数之间的差异来做后面的选择和优化。


转载自 https://www.wangyd.com/post/163

发表评论

注:*为必填

回复 的评论
*
选择
*
*