using ajax readystate 3 polling

This one is not news anymore, but anyway, a friend of mine asked about a function to notify the browser of changes on the backend, so with multiple online users you can notify a user of changes others make.

One way is a socket daemon, the other is using the ajax redystate 3 ‘polling’ feature (a bit like the comet server). As the ajax xhr-object is a basic http-wrapper, it has the same sequence of a normal http connection. A normal call is in readystate 3 (receiving data) until the server signals that was the end of it, readystate 4, where you can pick up the returned http-connection status (200, 404 etc.)

Using the php flush() command inside a running program, you force output to the browser, which triggers a readystate 3 change in an xhr instance. You can pick up on the triggered readystate change and read the new output in the buffer.

A demo is basic, and requires four files

  • queue.txt  (chmod 777)
  • polling.js
  • polling.php
  • polling.html

I put one queue.txt file on the backend with 777 permission so anyone can read and write it.

Then I make a javascript file containing two calls, startclock and stopclock (and makeXmlHttp() to make an xhr instance). Startclock starts an endless loop and outputs the incremental content of the output buffer to a div in the html file (for the demo I echo time(), that way you can make an ajax digital clock) :

  1. function startclock()
  2. {
  3.         var index = 0;            
  4.         xmlHttp = makeXmlHttp();
  5.        
  6.         xmlHttp.onreadystatechange = function()
  7.         {
  8.                 if ( xmlHttp.readyState == 3 )
  9.                 {
  10. //grab the new part of the output buffer and write it to a div
  11.     var rtlen = xmlHttp.responseText.length;
  12.            if (index < rtlen) {
  13.               document.getElementById("seoresult").innerHTML =  xmlHttp.responseText.substring(index);
  14.               index = rtlen;
  15.            }
  16.    }
  17.         }
  18.         xmlHttp.open("POST", "polling.php?action=start", true);
  19.         xmlHttp.send('');
  20. }

stopclock() just calls a php function that writes ‘stop’ in queue.txt :

  1. function stopclock()
  2. {
  3.         xmlHttp = makeXmlHttp();
  4.         xmlHttp.open("POST", "polling.php?action=stop", true);
  5.         xmlHttp.send('');
  6. }

For the sake of the demo, I added a function stopclock() that writes ‘stop’ to the queue.txt.

Then the polling.php program file : this contains a routine that runs an endless loop and three routines for the queue.txt file (write ‘start’, add ‘stop’, and read content). The endless loop reads queue.txt once every half second, if the word ‘stop’ is in there it ends, the php-program ends and the xhr call ends. Otherwise the endlessloop function outputs the time, and flushes the buffer to the browser :

  1. if($_GET['action']=='start') {
  2.  endlessloop();
  3. } else {
  4.         writestop();
  5. }
  6.  
  7.  
  8. function endlessloop() {
  9. //truncate the queue, write 'start'
  10.  writestart();
  11.  
  12. //get the time
  13.  $start=time();
  14.  
  15. //using while(1) or while(true) you start an endless loop,
  16. //and use break to end it, I tend to also use a timed end,
  17. //to prevent the program from running on endlessly on the
  18. //server if I break the http connection
  19.  
  20.  while(1) {
  21. //read the file contents
  22.   $the_Text=readsome();
  23.  
  24. //check if the word 'stop' is in there
  25. //if so, echo a notification, end the program
  26.   if(strpos($the_Text, "stop")>0) {
  27.    echo 'clock stopped';
  28.    flush();  
  29.    break;
  30.   }
  31.  
  32. //after 45 seconds (arbitrary) end the program anyway
  33.   if(time()>($start+45)) {
  34.    echo 'time elapsed';
  35.    flush();  
  36.    break;
  37.   }
  38.  
  39. //echo the time
  40.   echo time();
  41.  
  42. //wait for a while
  43.   usleep(100000);
  44.  
  45. //flush triggers a forced dump of the buffer to the browser
  46.   flush();
  47.  }
  48. }
  49.  
  50. function writestart() {
  51. //truncate the file, write 'start'
  52.  $fhandle =fopen('queue.txt', 'w');
  53.  fwrite($fhandle, 'start');
  54.  fclose($fhandle);
  55. }
  56. function writestop() {
  57. //write 'stop'
  58.  $fhandle =fopen('queue.txt', 'a');
  59.  fwrite($fhandle, 'stop');
  60.  fclose($fhandle);
  61. }
  62.  
  63. function readsome() {
  64. //read the file, return the text contents
  65.  $fhandle =fopen('queue.txt', 'r');
  66.  while($buffer = fread($fhandle, 1024)) {
  67.   $text.=$buffer;
  68.  }
  69.  return $text;
  70. }

If you start the same polling.html in two browser windows you’ll notice that stopping one, also causes the other to stop. Very basic demo.

Posted in php and tagged .

Leave a Reply

Your email address will not be published. Required fields are marked *