即使在浏览器窗口关闭后,仍然使用setTimeout继续执行AJAX


Continue to execute AJAX with setTimeout even after browser window is closed

我有一个PHP页面,其中包含一个AJAX请求到另一个PHP页面,其中包含一个casperJS脚本,由单击按钮触发,随后每60秒执行一次。

我希望能够关闭浏览器窗口,但仍然继续运行AJAX请求,直到停止按钮被按下。

我看过一些关于这个话题的帖子

  1. 脚本会在关闭页面后继续运行吗?
  2. 我怎么能使setInterval也工作时,标签是不活动的Chrome?
  3. 脚本事件不再触发当用户离开网站或关闭浏览器,即使应用程序仍然是活跃的

他们提到了PHP ignore_user_abort(),但这些主要关注的事实是,他们的脚本需要很长时间来执行,他们希望通过关闭浏览器窗口来防止过早终止。

目前,我的PHP站点与casperJS脚本设置的方式,我收到日志更新到一个。txt文件,以及电子邮件在任何错误的情况下,所以我能够看到脚本是否正在运行。

如果我启动AJAX请求并快速关闭浏览器窗口,则该AJAX请求将完成并登录.txt文件,但随后的setTimeout将被忽略。

我希望能够返回到关闭的窗口,仍然看到AJAX返回的当前状态,并且还能够在那个时候停止脚本(好像我从未离开/关闭浏览器窗口)。这可能吗?

我的AJAX请求的当前PHP代码:

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="style.css" type="text/css" media="screen, projection"/>
    <script src="jquery-2.1.1.min.js" type="text/javascript"></script>
    <script type="text/javascript" language="javascript" src="jquery.dropdownPlain.js"></script>
    <title>CasperJS Automated Testing Unit</title>
  </head>
  <center>
  <body>
  <div id="mainContent">
<p>Welcome to the CasperJS Automated Testing Unit</p>
  <button id="button_AJAX">Run CasperJS</button>
  <button id="button_STOP" onclick="myStopFunction()">Stop CasperJS</button>
  </div>
  <br>
  <div id="loading"></div>
<script type="text/javascript">
  $('#button_AJAX').click(function executecasperJS() {
     $('#loading').html('<img src="rays.gif"><br><i>Web harvesting in progress; please wait for test results.</i>');  
        $.ajax({  
          type: "GET",
          dataType: "text",
          url: "phpwithCasperJS.php",
      success: function (data) {        
                  $('#loading').html(data);
          } 
      }); 
timeout = setTimeout(executecasperJS,60000);  
});
    $("#button_AJAX").click(function() {$("#button_AJAX").text("CasperJS Executed");});
  $("#button_STOP").click(function() {$("#button_AJAX").text("Run CasperJS");});
  function myStopFunction() {
      clearTimeout(timeout);
  }
</script>
</div>
  <div id="page-wrap">
          <ul class="dropdown">
          <li><a href="#">CasperJS Logs</a>
            <ul class="sub_menu">
               <li><a href="casperjs_log.txt" target="_blank">Testing Log</a></li>
               <li><a href="casperjs_error.txt" target="_blank">Error Log</a></li>
        </ul>
  </div>
</center>
  </body>
</html> 

和存放我的casperJS脚本的PHP:

 <?php
date_default_timezone_set('America/Managua');
$date = date('m/d/Y h:i:s a', time());
    $time_start = microtime(true);
    $output = exec("/usr/local/bin/casperjs /path/to/script/casperJScript.js");
        if (strpos($output, 'Check for fail message') === FALSE) {
            require_once('../class.phpmailer.php');
    $mail             = new PHPMailer();
    $mail->IsSMTP();     
    $mail->SMTPDebug  = 1;                   
    $mail->SMTPAuth   = true;                  
    $mail->SMTPSecure = "ssl";                
    $mail->Host       = "smtp.gmail.com";      
    $mail->Port       = 465;                   
    $mail->IsHTML(true);     
    $mail->Username   = "emailaddress";  
    $mail->Password   = "password";            
    $mail->SetFrom('emailaddress');
    $mail->AddReplyTo("emailaddress");
    $mail->Subject    = "casperJS: Server failure occured on $date";
    $mail->Body    = "Body";
    $mail->AddAddress("emailaddress");
            if(!$mail->Send()) {
            } else {
            echo '<span style="color:#FF0000">The server has gone 100% failure and an email with the error has been sent.</span>';
            $myfile = fopen("../casperjs_error.txt", "a") or die("Unable to open file!");
            $txt = "ERROR log: $output on $date" . PHP_EOL ;
            fwrite($myfile, $txt);
            fclose($myfile);
              echo "<br />";
              echo "<br />";
            }   
        }
        echo "Test Results: $output";
        $time_end = microtime(true);
        $time = $time_end - $time_start;
        echo "<br />";
        echo "<br />";
        echo "Test completed in $time seconds'n on $date";
        $myfile = fopen("../casperjs_log.txt", "a") or die("Unable to open file!");
        $txt = "Log: $output on $date" . PHP_EOL ;
        fwrite($myfile, $txt);
        fclose($myfile);
    ?>

不能在浏览器窗口关闭后触发AJAX请求。

在任何情况下,为什么要依赖周期性的AJAX (HTTP)请求来继续一些服务器端进程?别那样做。

相反,组织长时间运行的流程在服务器端启动(可能是响应客户端请求)。然后,您只需要在客户机上发出HTTP (AJAX或其他)请求,就可以查看服务器端作业的"进度"。

一旦浏览器不再在当前页面的上下文中执行,任何可能仍在执行的JavaScript都将被终止。通常,您会注意到这样的行为,因为用户按下了停止按钮,关闭了窗口,或者移动到另一个页面。例如,当我在stack overflow(和相关网站)上投票时,如果我立即投票(赞成或反对),然后点击标题栏返回问题列表,我的手机通常会出现错误。但是,服务器通常会完成请求,因为当我回到问题列表时,投票已经反映出来,尽管有错误。

请注意,对于短请求,只要服务器接收到整个HTTP有效负载,它将执行请求直到完成,尽管用户可能永远不会意识到这一事实。一般来说,卸载页面有这些效果:任何"onunload"或类似事件被触发,任何现有的AJAX请求自动失败,如果互联网连接已经终止(例如关闭WiFi或网络适配器),以及所有与"unload"无关的事件被终止,例如"onclick","onkeypress"等,具体包括"setTimeout"answers"setInterval"事件。如果你必须知道发生了什么,你可以尝试一个弹出窗口,但用户的弹出窗口设置或弹出窗口拦截器可能会禁止这个最后的策略来知道页面将被卸载。

总之,客户机很可能不会执行任何发送给服务器的最终通知,而服务器通常也不会注意到客户机的消失。您可以通过使用Comet来减少这种影响,Comet是一种长轮询方法,它至少能够将连接关闭事件通知服务器,这是您能够"保证"服务器能够注意到页面最终消失的最接近的方法。但是,Comet也有自己需要注意的限制,包括服务器端资源使用量的增加,以及对不同类型事件的敏感性,包括Internet连接的丢失(也就是说,无法检测用户关闭页面和完全失去连接之间的区别,您所看到的只是套接字上的连接丢失)。