2014-11-01 93 views
1

According to MDN,XMLHttpRequestreadyState事件觸發5個事件,如下所示。XMLHttpRequest readyState HEADERS_RECEIVED等待整個文件下載

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_RECEIVED,LOADINGDONE都等待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請求,那麼完整的請求。這是預期的行爲還是我錯過了什麼?

UPDATE:

使用符號鏈接通過較慢的網絡共享一個1GB的文件,或該輸出輸出顯着量的(下面的例子)不觸發HEADERS_RECEIVED越早的PHP文件。雖然這似乎有點不可靠。我曾嘗試在sleep之前使用PHP的flush函數,但它沒有幫助。

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

有沒有一種方法可靠地發送標題,而無需等待內容發送?

回答

1

至少在你的例子中,我猜PHP實際上並沒有沖洗緩衝區(並因此發送頭文件),直到睡眠之後,但我不確定這是否能解釋這種行爲if你使用實際的文件下載遇到了它。

+0

你似乎在做某事。查看我的更新。 – 2014-11-01 02:33:45

+0

我相信PHP中的輸出緩衝區只會用'ob_flush()'刷新,我不相信'flush()'會這樣做。嘗試使用'ob_flush()'。 – AlpineCoder 2014-11-01 14:04:45

+0

有趣。我的理解是,'ob_flush'只有在你以編程方式使用'ob_start'時纔是必要的,但事實證明PHP可以(總是)自動創建一個輸出緩衝級別。看起來你可以通過調用'ob_get_level'來檢測它是否爲非零。 'ob_flush'本身是不夠的。看起來你必須首先調用'ob_flush',然後_then_'flush'來首先刷新內部緩衝區,然後發送給客戶端。這使事情更加複雜,但感謝您的幫助! – 2014-11-01 15:21:08