AJAX from the darksideFiled: Mon, Dec 18 2006 under Programming|| Tags: ajax php process buffer When it comes to AJAX, javascript gets all of the press while the server-side programs javascript calls do most of the work with none of the glory. Mostly, this is because very little needs to be done to a server side program to differentiate it from AJAX and non-AJAX calls. At most, people who use AJAX with Internet explorer will go into a panic until they discover cache control headers for their server side code which prevent IE from caching AJAX calls. So what can possibly be worth writing an article about server side AJAX processing? How about the ability to process data after you've finished sending data back to the browser? With AJAX the speed of the transaction makes or breaks the application. If you have a fast turnaround you'll have a solid app every bit as viable as a local application. On the other hand, if your server calls are taking forever you not only risk breaking the clientside scripts but alienating and losing your visitors. So anything you can do to decrease the turn-around time between client and server is worth looking into. To this end, one of the best possible things you can do is to pump the feedback to your browser as fast as you can, then close the connection and let the server continue to process the transaction even after the browser connection has been closed. It's not great in EVERY circumstance but it is a real lifesaver -- and more importantly, timesaver -- in a surprising number of cases. When I was working on the Launch page for this site I set up an infinite Flickr filmstrip. As the user dragged the filmstrip from left to right, the far side of the queue was stripped and new images were requested from the server. One of the immediate problems that cropped up was network latency. To get new images I had to have the browser make the request to my web-server which then had to make a few calls to Flickr before it could format the data and send it back to the browser. The solution was to keep a cache of images on the server and send those immediately back to the browser and then have the server side program get a new batch of images from Flickr to save in the cache for the next time. In theory this was great, in practice, nothing was sent back to the browser and processed until the server program finished its processing and closed the http connection. In short, the delay was just as long only now we had an extra step of storing image data to the server hard drive. After a little research, I discovered it was possible to send data back to the browser, close the http connection, and let the php program continue to run. Moreover this trick turned out to be surprisingly simple! Take a look.
header("Cache-Control: no-cache, must-revalidate"); // Cache control headers
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // For Internet Explorer
header("Connection: close"); // Indicate we will close the connection
ob_start(); // Start sending all output to a buffer (not browser!)
////////////////////////////////
// Your normal output goes here.
readfile('sampledata.txt'); // data to be sent back to browser (stored in buffer!)
//
// Done sending output to the browser
////////////////////////////////
$size=ob_get_length(); // Get the number of bytes in our buffer
header("Content-Length: $size"); // Send a header which states how many bytes
// we're sending, when this # is reached
// connection will close (as per the header above)
ob_end_flush(); // Output all the data in our buffer.
flush(); // Flush stdout (REALLY send all the stuff to browser)
// Data has been sent to the browser, the http connection is now closed
// rest of your program goes here...
As you can see, after the first 2 cache control headers, we have a header which indicates the connection will be forcibly closed. After that we start recording the output buffer with ob_start. After we're done buffering the data we record the number of bytes in the output buffer, issue another header (content-length) with the number of bytes in the buffer, then we flush the buffers. Because we specified the connection would be forcibly closed and supplied the number of bytes to be received, the browser will close the connection automatically once it has received all of the data we told it we were going to send. After the flush, the browser connection is closed and your program is still running; which will let you finish processes the data without making your visitor wait. File this under totally cool, non-obvious stuff.
|