【问题标题】:Continue to execute AJAX with setTimeout even after browser window is closed即使在浏览器窗口关闭后也继续使用 setTimeout 执行 AJAX
【发布时间】:2014-07-27 06:35:31
【问题描述】:

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

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

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

  1. Will a script continue to run even after closing a page?
  2. How can I make setInterval also work when a tab is inactive in Chrome?
  3. Scripting events no longer fire when a user leaves site or closes browser even though app is still active

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

目前,我使用 casperJS 脚本的 PHP 站点的设置方式,我会收到 .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);
    ?>

【问题讨论】:

标签: javascript php jquery ajax casperjs


【解决方案1】:

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

无论如何,您为什么要依靠周期性的 AJAX (HTTP) 请求来继续某些服务器端进程?不要那样做。

相反,组织在服务器端启动长时间运行的进程(也许是为了响应客户端请求)。然后,您只需在客户端发出 HTTP(AJAX 或其他)请求,即可查看服务器端作业的“进度”。

【讨论】:

  • 您好,感谢您的回复。所以你建议使用 PHP GearmanWorker::setTimeout?但是,如果我关闭浏览器窗口,我怎么能阻止它呢?重新打开页面后,按停止按钮将无济于事,因为它不再有 AJAX (HTTP) 请求。
  • 我不是在建议 GearmanWorker 或任何其他特定模块,只是一种方法。您可能需要跟踪浏览器(会话、身份验证或本地存储等)以跟踪哪个请求属于哪个服务器端进程。
【解决方案2】:

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

请注意,对于短请求,只要服务器接收到整个 HTTP 有效负载,它就会执行请求直到完成,尽管用户可能永远不会意识到这一事实。通常,卸载页面会产生以下影响:任何“onunload”或类似事件被触发,任何现有的 AJAX 请求都会自动失败,就好像 Internet 连接已被终止(例如关闭 WiFi 或网络适配器),并且所有事件都不是专门针对与“卸载”相关的终止,如“onclick”、“onkeypress”等,具体包括“setTimeout”和“setInterval”事件。如果您必须知道发生了什么事情,您可以尝试弹出窗口,但用户弹出窗口设置或弹出窗口阻止程序可能会禁止这一最终策略以知道页面将被卸载。

总而言之,客户端很可能不会向服务器发送任何最终通知,服务器通常不会注意到客户端的消失。您可以通过使用 Comet 来减少这种影响,这是一种长轮询方法,至少能够通知服务器连接关闭事件,这是您可以“保证”服务器会注意到页面最终消失的最接近的方法.然而,Comet 有其自身需要注意的局限性,包括服务器端资源的使用增加,以及对不同类型事件的敏感性,包括 Internet 连接中断(即,无法检测到用户关闭页面与完全断开连接之间的区别,您将看到的只是套接字上的连接断开)。

【讨论】:

    猜你喜欢
    • 2016-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    • 2016-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多