php与ajax交互——实现php实时返回结果给ajax,并在后台保持继续运行的方法

最近做个人项目的时候,遇到一个问题,就是点击页面上一个按钮后,通过ajax调用php接口,ajax根据返回的数据对页面做一些改变。但同时,这个按钮点击后要存储大量的数据到数据库中。由于前端页面的变化要求快速响应,因此需要php快速返回计算结果,然后后台继续运行与数据库的交互部分代码。由于php返回给ajax数据是通过echo形式,因此第一时间想到flush函数,然而试了下却发现行不通,于是在网上找了下办法,发现大部分是针对html页面的实时交互,这类方法对ajax是无效的。如(引用网上代码):

set_time_limit ( 0 );
ob_end_clean ();
ob_start ();
$i = 10;
while ( $i > 0 )
{
 $flush = $i . "<br/>";
 #Microsoft Internet Explorer 只有当接受到的256个字节以后才开始显示该页面,
 #所以必须发送一些额外的空格来让这些浏览器显示页面内容
 $flush = str_pad ( $flush, 1000 );
 echo $flush;
 ob_flush ();
 flush ();
 sleep ( 1 );
 $i --;
}

这种方式适用于直接输出结果到页面,而不能返回结果给ajax。这两种方式的区别如下:
在浏览器访问时能成功的原因是:浏览器在接收缓冲区装满时,就立即解释收到的数据,而不等待通讯的结束
在Ajax访问时不成功的原因是:XMLHttpRequest组件只负责交换数据,不负责处理数据。处理数据的代码要等到通讯结束后才执行。如果Ajax不以XMLHttpRequest 做传输载体,而以 iframe 做载体的话,上述代码是可以成功的。

后来实在没找到解决办法,可能是我搜索水平有限。。。
没办法只能去stackoverflow上求助,幸好我的英语能凑合描述清楚问题,得到了两位外国友人的帮助,成功解决。下面看下大牛提供的方法(自己补了一点中文注释):

//省略php接口中处理数据的代码
 echo json_encode($res);//返回结果给ajax
 // get the size of the output
 $size = ob_get_length();
 // send headers to tell the browser to close the connection
 header("Content-Length: $size");
 header('Connection: close');
 ob_end_flush();
 ob_flush();
 flush();

 /******** background process starts here ********/
 ignore_user_abort(true);//在关闭连接后,继续运行php脚本
 /******** background process ********/
 set_time_limit(0); //no time limit,不设置超时时间(根据实际情况使用)
 /******** Rest of your code starts here ********/
 //继续运行的代码
 ...
 ...

不得不说老外解答问题很有耐心,两个回答都写了很多注释,思路一目了然,我就不再赘述了。

PS:由于php的特性,因此在后台运行代码,依然会影响对其他请求的处理,所以对于长时间运行的代码可以考虑另起一个进程来处理,或使用多线程(swoole),或者使用消息队列(如rmq)等方式来代替。

水平有限,欢迎指正~

参考:
http://fc-lamp.blog.163.com/blog/static/174566687201271025332854/
http://bbs.csdn.net/topics/390843794
http://stackoverflow.com/questions/37182850/how-to-php-send-result-to-ajax-immediately/37183216#37183216

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值