欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

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 --;
}12345678910111213141516

这种方式适用于直接输出结果到页面,而不能返回结果给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 ********/
 //继续运行的代码
 ...
 ...12345678910111213141516171819

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

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

来自  http://blog.csdn.net/u011832039/article/details/51387548

普通分类: