2

I have a PHP page with an AJAX requested to another PHP page which houses a casperJS script, triggered by a button click and subsequently executed every 60 secs.

I would like to be able to close the browser window but still continue to run AJAX requests, until the Stop button is pressed.

I have seen some of the posts on this topics

  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

They mention PHP ignore_user_abort() but these mainly focus on the fact that their scripts take a very long time to execute and they want to prevent early termination by closing browser window.

Currently, the way my PHP site with the casperJS script is set up, I receive log updates to a .txt file, as well as an email in case of any errors, so I am able to see if the script is running or not.

If I start the AJAX request and quickly close my browser window, that one AJAX request will finish and log in the .txt file, but the subsequent setTimeout is ignored.

I would like to be able to return to the window that was closed and still see the current status of the AJAX returns, and also be able to at that time Stop the script (as if I had never left/closed the browser window). Is this possible?

My current PHP code for my AJAX request:

<!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> 

And the PHP which houses my casperJS script:

 <?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);
    ?>
Community
  • 1
  • 1
gothamgator
  • 111
  • 1
  • 11
  • 3
    "after browser window is closed" --- it's like asking to run JS on a machine that is turned off. – zerkms Jul 27 '14 at 06:52
  • Similar question in different language: http://stackoverflow.com/questions/23573393/how-to-manage-server-side-processes-using-mysql/23577751#23577751 – David-SkyMesh Jul 27 '14 at 06:55

2 Answers2

2

You cannot fire AJAX requests after the browser window is closed.

In any case, why do you rely on periodic AJAX (HTTP) requests to continue some server-side process? Don't do that.

Instead, organise for the long-running process to be started on the server-side (perhaps in response to a client-side request). Then you need only make HTTP (AJAX or otherwise) requests on the client to see the "progress" of the server-side job.

David-SkyMesh
  • 5,041
  • 1
  • 31
  • 38
  • Hi, thanks for the reply. So you are suggesting using a PHP `GearmanWorker::setTimeout`? But then how would I be able to stop it if I close the browser window? Once I re-open the page, pressing the Stop button won't help since it no longer has an AJAX (HTTP) request. – gothamgator Jul 27 '14 at 07:10
  • I'm not suggesting GearmanWorker or any other specific module, only an approach. You'll likely need to track browsers (sessions, authentication or localStorage, etc) to keep track of which request belongs to which server-side process. – David-SkyMesh Jul 27 '14 at 07:20
0

Once the browser is no longer executing in the current page's context, any JavaScript that may still be executing is subject to termination. Usually, you'll notice such behavior because the user pressed the stop button, closed the window, or moved to a different page. For example, when I'm voting on stack overflow (and related sites), I'll usually get an error on my phone if I immediately vote (up or down), then click on the title bar to go back to the list of questions. The server usually finishes the request, though, because by the time I'm back on the list of questions, the vote has been reflected, despite the error.

Note that for short requests, as long as the server's received the entire HTTP payload, it will execute the request to completion, although the user may never be aware of that fact. Generally, unloading the page has these effects: any "onunload" or similar events are fired, any existing AJAX requests are automatically failed as if the Internet connection had been terminated (e.g. turning off the WiFi or network adapter), and all events not specifically related to "unload" are terminated, such as "onclick", "onkeypress", etc, and specifically including "setTimeout" and "setInterval" events. If you must know that something occurred, you can try a popup window, but the users popup settings or popup blocker may prohibit this one final gambit to know the page is going to be unloaded.

In summation, the client most likely won't honor any final notifications to the server, and the server generally won't notice the client's disappearance. You can reduce this effect by using Comet, a long-polling method that will at least be able to notify the server of a connection close event, which is the closest you can get to "guaranteeing" that the server will notice the page's final disappearance. Comet, however, has its own limitations that you'd want to be aware of, including the increased usage of server-side resources, and susceptibility to different types of events, including a loss of Internet connectivity (namely, there's no way to detect the difference between the user closing the page and a total loss of connectivity, all you'll see is a loss of connectivity on the socket).

sfdcfox
  • 235
  • 4
  • 12