不等待来自AJAX请求的响应

时间:2011-07-21 19:54:43

标签: php javascript ajax

假设我将jQuery的AJAX HTTP请求发送到后端PHP脚本。请求发出后,PHP脚本开始运行并发挥其魔力。假设我转到另一个网站,远离原始AJAX请求的网站。同样,我在PHP脚本完成之前执行此操作,并有时间回复HTTP响应。即使在我收到HTTP响应之前我已经切换到另一个网站,PHP脚本是否已完成运行并执行其操作?

所以顺序就是这样。

  • 我在网站www.xyz.com
  • 我有一个jQuery处理程序,可以将一个AJAX请求发送到blah.php
  • blah.php开始运行
  • 我很快就去了网站www.abc.com,没有等到blah.php的回复

blah.php发生了什么事?执行还在继续吗?它停止了吗?我的意思是它没有机会回应......

4 个答案:

答案 0 :(得分:8)

这可能取决于您的服务器配置,但通常,尽管已关闭HTTP连接,脚本仍将继续执行

我用Apache 2 + PHP 5测试了这个作为mod_php 。我希望PHP与CGI和其他网络服务器有类似的行为,但不确定。

确定配置的最佳方法是,@tdammers建议:设置类似以下内容的测试脚本并监控日志。

<?php
error_log('Test script started.');
for ($i = 1; $i < 13; $i++) {
    sleep(10);
    error_log('Test script got to ' . (10 * $i) . ' seconds.');
}
error_log('Test script got to the end.');
?>

访问此脚本(在/test.php或其他任何位置),然后在获得任何结果之前,在浏览器上点击停止。这相当于在XHR返回之前导航。您甚至可以将其作为XHR的目标并导航。

然后检查您的错误日志:您应该有一个开始,然后每隔10秒发送一次消息,持续两分钟和结束。您可以修改$i的高度,以确保您的脚本达到预期的最长执行时间,如果您也想测试它。

您不必使用error_log() - 您可以写入文件,或者在服务器上进行一些其他持久性更改,而无需保持客户端连接处于打开状态。

由于max_execution_time php.ini指令,脚本执行时间可能会在此之前停止 - 但无论如何这应该与Web服务器超时时不同。

答案 1 :(得分:6)

尝试ignore_user_abort(true);

ignore_user_abort(true);

它不应该中止代码的处理

答案 2 :(得分:0)

您可能想查看This Question的答案。 基本上当你对调用exec()函数的php函数进行ajax调用时,如问题的答案所示,你几乎可以立即获得一个ajax响应,因为你的php函数实际上并不需要处理任何东西。这样,用户是否离开页面无关紧要。 这是一个小例子:

在html文件中调用ajax:$.ajax({url: 'blah.php'});

blah.php文件:exec('bash -c "exec nohup setsid php really_slow_script.php > /dev/null 2>&1 &"');

最后在really_slow_script.php中,只包含您想要运行的实际代码。

我成功使用了这种逻辑,允许用户将已上传的视频从我们网站上的帐户发布到youtube。 (视频必须发送到youtube,因为视频通常是大文件,我不希望用户在视频上传到youtube时必须等待)

答案 3 :(得分:0)

导航将触发服务器上的断开连接消息。 The implications of that entirely depends on what what your server has been configured to do

默认情况下,将设置服务器,以便断开连接不会中断程序运行的方式。但是,可以使用户断开连接将触发已注册register_shutdown_function的函数,将发生垃圾收集,脚本将终止。

因为它可以配置几个不同的地方,所以最简单的方法就是运行测试,但这是一个php.ini指令。如果要在全局级别配置它,可以在php.ini中设置ignore_user_abort = Off。如果您希望在特定于站点的级别上执行此操作,则可以在当前站点的父目录中的htaccess中使用php_value ignore_user_abort off。否则,您可以使用ignore_user_abort(false);

当然,在共享服务器上无法保证您可以控制htaccess或php.ini,因此您可能只需要使用ignore_user_abort(false);