According to MDN, the XMLHttpRequest
readyState
event fires 5 events, listed below.
0 UNSENT open()has not been called yet.
1 OPENED send()has not been called yet.
2 HEADERS_RECEIVED send() has been called, and headers and status are available.
3 LOADING Downloading; responseText holds partial data.
4 DONE The operation is complete.
This would seem to suggest that the HEADERS_RECEIVED
would be available before the entire file has downloaded, especially during a long transfer. However, in my testing, while the events do fire in this order, both HEADERS_RECEIVED
and LOADING
fire at virtually the same time as the DONE
event.
Here is a basic example that illustrates my issue. The OPENED
event fires immediately, but HEADERS_RECEIVED
, LOADING
, and DONE
all wait 5 seconds. I ran this test with PHP 5.5 on a local Apache 2.4 server in both Firefox and Chrome.
JavaScript:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
console.log("readyState:", xmlhttp.readyState);
};
xmlhttp.open("GET", "handler.php", true);
xmlhttp.send();
handler.php:
<?php
header( 'Content-Type: text/plain' );
echo "start
";
sleep( 5 );
echo "end
";
It seems the only way to get the headers before the content is to first make a HEAD
request, then a full request. Is this expected behavior or am I missing something?
UPDATE:
Using a 1GB file symlinked over a slow network share, or a PHP file that outputs a substantial amount of output (example below) does fire the HEADERS_RECEIVED
sooner. This seems to be somewhat unreliable though. I've tried using PHP's flush
function before sleep
, but it doesn't help.
<?php
header( 'Content-Type: text/plain' );
echo "start
";
$i = 10000000;
while( $i-- ){
echo "1
";
}
echo "end
";
Is there a way to reliable send headers without waiting for the content to send?