XMLHttpRequest readyState HEADERS_RECEIVED等待整个文件下载

时间:2014-11-01 01:48:54

标签: javascript php ajax apache xmlhttprequest

According to MDNXMLHttpRequest readyState事件会触发5个事件,如下所示。

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.

这似乎表明在整个文件下载之前HEADERS_RECEIVED可用,尤其是在长时间传输期间。但是,在我的测试中,当事件按此顺序触发时,HEADERS_RECEIVEDLOADING几乎与DONE事件同时发生。

这是一个说明我的问题的基本示例。 OPENED事件会立即触发,但HEADERS_RECEIVEDLOADINGDONE都会等待5秒。我在Firefox和Chrome的本地Apache 2.4服务器上运行PHP 5.5测试。

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\n";
sleep( 5 );
echo "end\n";

在内容之前获取标题的唯一方法是首先发出HEAD请求,然后是完整请求。这是预期的行为,还是我错过了什么?

更新

使用通过慢速网络共享符号链接的1GB文件或输出大量输出的PHP文件(例如下面的代码)会更快地触发HEADERS_RECEIVED。但这似乎有点不可靠。我在sleep之前尝试过使用PHP的flush功能,但它没有帮助。

<?php
header( 'Content-Type: text/plain' );
echo "start\n";
$i = 10000000;
while( $i-- ){
    echo "1\n";
}
echo "end\n";

有没有办法可靠地发送标头而无需等待内容发送?

1 个答案:

答案 0 :(得分:1)

至少在你的例子中,我猜测PHP实际上并没有冲洗缓冲区(因此发送标题)直到睡眠之后,但我不确定是否如果您使用实际文件下载遇到它,我会解释这种行为。