在PHP中响应ajax请求后如何继续处理?

在PHP中响应ajax请求后如何继续处理?,php,ajax,timeout,Php,Ajax,Timeout,有些操作花费太多时间,这导致ajax请求超时 如何首先完成对请求的响应,然后继续该操作?生成一个后台进程并返回后台进程id,以便用户稍后可以通过某个秘密URL进行检查。指令和函数可能就是您要寻找的:它应该允许您将响应发送到浏览器,然后,仍然在服务器上运行一些计算 您可能会对这篇文章感兴趣:如何使用ignore_user_abort()进行带外处理;引述: 编辑2010-03-22:在看到@Joel的评论后,删除了链接(指向http://!waynepan.com/2007/10/11/!how-

有些操作花费太多时间,这导致ajax请求超时


如何首先完成对请求的响应,然后继续该操作?

生成一个后台进程并返回后台进程id,以便用户稍后可以通过某个秘密URL进行检查。

指令和函数可能就是您要寻找的:它应该允许您将响应发送到浏览器,然后,仍然在服务器上运行一些计算

您可能会对这篇文章感兴趣:如何使用ignore_user_abort()进行带外处理;引述:
编辑2010-03-22:在看到@Joel的评论后,删除了链接(指向
http://!waynepan.com/2007/10/11/!how-to-use-ignore\u user\u abort-to-do-process-out-of-band/
——删除空格并
,如果您想尝试)

基本上,当你使用
ignore\u user\u abort(true)
在php中 脚本,脚本将继续 即使用户按下 esc或在浏览器上停止。你怎么 用这个<一个用途是 将内容返回给用户并允许 正在运行时要关闭的连接 处理不需要的事情 用户交互

下面的示例发出
$response
发送给用户,关闭 连接(使浏览器的 旋转器/加载杆停止),然后 执行
do_函数需要五分钟()

举个例子:

ignore_user_abort(true);
header("Connection: close");
header("Content-Length: " . mb_strlen($response));
echo $response;
flush();
do_function_that_takes_five_mins();
(还有更多我没有复制粘贴)


请注意,您的PHP脚本仍然必须符合
max\u execution\u time
memory\u limit
约束,这意味着您不应该将其用于花费太多时间的操作

这还将使用一个Apache进程——这意味着您不应该有几十个页面同时执行此操作


不过,我认为这是一个增强使用体验的好方法;-)

您需要调用
flush()
将响应立即发送到浏览器。

这取决于您试图完成的任务

在我的例子中,我需要做大量的服务器端处理,只需要将少量数据发送回浏览器——实际上是摘要信息

我试图创建一个消息发送者-向250多人发送电子邮件,但可能更多(取决于有多少人在系统中注册)

PHP邮件处理程序速度很快,但对于大量邮件,速度不够快,因此它肯定会超时。为了解决这个问题,我需要延迟服务器/PHP端的超时,并保持浏览器挂起,直到所有数据汇总并显示

我的解决方案——一个挑逗者

基本上,我给用户一条消息,说明一些初始统计信息(试图发送这么多电子邮件),创建了两个DIV框(一个用于当前状态信息,第二个用于最终摘要信息),显示页脚,开始处理,完成后更新摘要信息。内容如下:

从收集要处理的数据开始,并获取一些摘要信息。在我的例子中,我提取了电子邮件地址列表,验证了它们,并对它们进行了计数

然后显示“正在尝试”信息:

现在浏览器开始显示内容,我们需要给用户一些东西看,所以这里有一个提示-我们将创建一个状态栏,显示在内部DIV中,并为外部DIV创建最后一条消息

因此,当您循环浏览数据时,定期(我将“多久”留给您来确定),输出以下内容:

set_time_limit (3);
...
(process your data here)
...
<script>document.getElementById('progress').innerHTML  += "<img src='images/progress_red.gif' width: $width height=20 border=0>"</script>
flush();
设置时间限制(3);
...
(在此处处理您的数据)
...
document.getElementById('progress')。innerHTML+=“”
冲洗();
这实际上是将小4x20 progress_红色图像堆叠在一起,使其看起来像是一个红色条在屏幕上移动。在我的例子中,我做了100次,基于我当前正在处理的数量占要处理的总数的百分比。“set_time_limit”将在现有限制的基础上增加3秒,这样您就知道您的脚本不会运行到PHP时间限制墙中。根据需要调整应用程序的3秒钟时间

尽管页面在技术上是“完整的”,javascript代码将更新DIV html,我们的进度条将“移动”

完成后,我会报告实际处理了多少项,并将其添加到外部DIV html中,页面就完成了:

<script>document.getElementById('content').innerHTML  += "Message was sent to $sentcnt people."</script>
document.getElementById('content')。innerHTML+=“消息已发送给$sentcnt人员。”
浏览器很高兴,因为它满足了所有的条件(从语法上来说,页面的末尾),用户看到一些事情一直发生,服务器也看到了

如果我能帮助的话,我倾向于不使用Javascript,但在这种情况下,没有通过Javascript完成任何花哨的CSS内容,因此它非常简单,很容易看到浏览器站点上发生了什么,并且开销很低。而且它的运行非常平稳


我并不认为这是完美的,但对于一个简单、低开销的解决方案,它对我来说是有效的,而不需要创建cronjobs、额外的队列机制或辅助进程。

它不起作用。你可以尝试以下方法来查看它:忽略用户中止(true);标题(“内容类型:文本/普通”);标题(“连接:关闭”);呼应‘某物’;睡眠(20);退出();响应仍然需要20秒。指向“如何使用ignore_user_abort()进行带外处理”的链接包含恶意软件(当通过推荐人查看时,也是如此)。看起来博客所有者被黑客攻击了…@Joel:谢谢你的评论;我已编辑我的答案以删除链接;;我刚刚离开了URL,没有超链接,并警告说实际上这是可行的,只是别忘了先回显255个字符,否则IE不会关闭连接…为了让它工作,并且不改变最大执行时间
ignore_user_abort(true); 
flush();
set_time_limit (3);
...
(process your data here)
...
<script>document.getElementById('progress').innerHTML  += "<img src='images/progress_red.gif' width: $width height=20 border=0>"</script>
flush();
<script>document.getElementById('content').innerHTML  += "Message was sent to $sentcnt people."</script>