Forum Moderators: open
In any case, I test with a number of browsers. The tool I developed produces a log that shows which callbacks are being sent when, and it revealed some interesting results that highlighted some browser differences.
First, a bit of background:
The XMLHTTPRequest Object [w3.org] is a JavaScript "facade" over the basic HTTP Request [w3.org] and HTTP Response [w3.org]. It encapsulates them into a single object and greatly reduces the underlying complexity.
These two actions form the underpinnings of the Web. Almost every action on a Web site is dictated by these.
Basically, the way it works is thus:
First, a browser initiates a HTTP Request [w3.org]. This can be done via GET or POST. In GET, the URL is complete with all data. In POST, it is sent separately. There's actually a heck of a lot more that can (and will) go on here, but, for the purposes of AJAX, the basic GET and POST is pretty much what we concern ourselves with.
After the browser makes its HTTP Request [w3.org], the server responds with a HTTP Response [w3.org].
This is all hidden inside the object, so you only see four different statuses, along with some data. For my purposes, I only look at the responseText [w3.org] data member, which has the actual text spit up by the server. There are a number of other fields which can be quite useful, but I try to keep things simple.
There is another data member, readyState [w3.org], which contains a simplified summary of the response state. There are four possible values for this:
0 Uninitialized
1 Open
2 Sent
3 Receiving
4 Loaded
Read the W3C Page [w3.org] to find out more about these.
What it boils down to, is that:
0 Is pretty much useless.
1 Just means that the browser is getting ready to send it.
2 Means that it sent it, but no guarantees the server is ready to digest it yet.
3 Means the server has got it and is gonna get back to us.
4 Means the server is done with the request, and washes its hands of it.
In my testing, 3 and 4 always happened at the same time. I didn't get 3 until the server was done processing, and 4 immediately followed 3.
Here's what my testing turned up. I tested the following browsers on Mac OS (I'm a Mac person):
Firefox 2 [en-us.www.mozilla.com] (with the WebDeveloper Extension [chrispederick.com])
Apple Safari [apple.com] (10.4.8 Version)
Opera 8.02
Opera 9.1 [opera.com]
iCab 3.01 [icab.de] (This is an excellent testing browser)
On Windows, I tested with:
Firefox 2
Microsoft Internet Explorer 6
Microsoft Internet Explorer 7
Opera 9.1
My tests consisted of using a testbed that allows threaded, simultaneous requests, or queued, sequential requests. These tests were done with both.
With the testbed version, I have a method of triggering 144 requests, one right after the next, so they are virtually simultaneous. The queued version will hold one request until the previous one has completed. I have it set up so that each URL is different. This has a real effect on the way the browsers behave. The test consists of calling a simple PHP file that executes a 2-second delay before spitting out a bit of text.
Here's what I noted:
Basically, the same browser supported on both platforms (Firefox and Opera) behaved exactly the same, regardless of the platform.
Response Stages:
In Firefox, you get an immediate Stage 1 callback, and a Stage 2 callback almost immediately after that.
In Opera, you don't get any callbacks at all until Stage 3.
In iCab, you don't get the Stage 1 callback, but you do get an immediate Stage 2 callback.
In IE, Safari and iCab, you won't get any response text until Stage 4.
In Safari, you don't get a response until Stage 2, and that is not immediate (iCab is immediate).
In none of the browsers did I get a Stage 0 callback.
The lesson here is that you can't depend on squat until Stage 3, and you can't use response text until Stage 4.
Sequence:
Firefox seems to have an internal queue, and the requests execute fairly sequentially. Stage 1 is reached immediately for all requests, but Stage 2, 3 and 4 come in directly sequentially for each request. There is a bit of mixing. It looks like it does two connections at a time, and executes the second of the pair first.
Various browsers had varying numbers of connections that executed sequentially. Firefox seems to do two at a time. Opera seems to do 8 at a time.
Opera 8 was completely sequential. There was no "mixing" of the requests. Opera 9 was all over the place.
Apple Safari seemed to be the fastest to finish all 144 requests.
Opera 8 and 9 seemed to give back the most control to the user. Firefox and iCab were the worst "control freaks."
iCab locked up on the "full bore" test. I couldn't complete this test, and force-quit the app after about ten minutes.
Opera has a rather annoying bug. This occurred in both 8 and 9: If the URL is exactly the same, the PHP file results are cached, and all the requests terminate as soon as the first result is returned. IE does the same, but I was able to fix it by spitting out a couple of "no-cache" headers. Opera ignores these headers.
I fixed that by adding an "id=" parameter to the URL, which made each URL unique. This forced Opera to stop caching.
This is just what I found from my rather informal testing. The results seemed interesting enough to share.
[edited by: DrDoc at 6:42 pm (utc) on Dec. 21, 2006]
[edit reason] JS Forum Charter [WebmasterWorld.com] [/edit]
you can't use response text until Stage 4because there is no response text until the server tries to handle the request, unless you count ACKs as a response.
I, too have noted the caching issue with IE(6), however I haven't been able to get it to recognize a no-cache header when using dynamic content. i.e. call to the same PHP file with different parameters. Is there anything other than no-cache headers that worked, for you?
Here's the complete text of my little PHP file:
<?php
header ( "Pragma: no-cache" );
header ( "Cache-Control: no-cache" );
$delay = $_POST['delay'];
if (!$delay )
{
$delay = $_GET['delay'];
}
$id = $_POST['id'];
if (!$id )
{
$id = $_GET['id'];
}
$t = (time() + (abs ( $delay )));
while ( time() <= $t ) {};// Real, REAL basic delay
if ( $id )
{
echo "(ID: $id) ";
}
echo "The request took $delay seconds to execute on the server.";
?>
obj.setRequestHeader('If-Modified-Since', 'Wed, 15 Nov 1995 00:00:00 GMT');
where 'obj' is obviously your XMLHTTP object. I have it like this:
if(obj!=null){
obj.onreadystatechange = onResponse;
obj.open("GET", ajaxUrl, true);
obj.setRequestHeader('If-Modified-Since', 'Wed, 15 Nov 1995 00:00:00 GMT');
obj.send(null);
}
onResponse is just a my function which handles the responseText and readyState code.
User Friendly for December 15th, 2006 [ars.userfriendly.org]