淺析 ProgressEvent 介面及其應用:上傳檔案進度事件
一、ProgressEvent 介紹
ProgressEvent
介面是測量如 HTTP 請求(一個XMLHttpRequest
,或者一個 <img>
,<audio>
,<video>
,<style>
或<link>
等底層資源的載入)等底層流程進度的事件。
1、構造方法:ProgressEvent()
(en-US):用給定的引數建立一個ProgressEvent
事件。
2、屬性:同時繼承它的父元素 Event
的屬性。
(1)ProgressEvent.lengthComputable
:只讀。是一個Boolean
(en-US)
(2)ProgressEvent.loaded
(en-US) :只讀。是一個unsigned long long
型別資料,表示底層流程已經執行的工作總量。可以用這個屬性和 ProgressEvent.total
計算工作完成比例。當使用 HTTP 下載資源,它只表示內容本身的部分,不包括首部和其它開銷。
(3)ProgressEvent.total
(en-US) :只讀。是一個unsigned long long
型別資料,表示正在執行的底層流程的工作總量。當使用 HTTP 下載資源,它只表示內容本身的部分,不包括首部和其它開銷。
3、方法:同時繼承它的父元素 Event
的方法。
ProgressEvent.initProgressEvent()
(en-US),使用被棄用的 Document.createEvent("ProgressEvent")
方法,來初始化一個已經建立好的ProgressEvent
。
4、下面的示例為一個新建的XMLHTTPRequest
添加了一個 ProgressEvent
,並使用它來顯示請求狀態。
var progressBar = document.getElementById("p"),
client = new XMLHttpRequest()
client.open( "GET", "magical-unicorns")
client.onprogress = function(pe) {
if(pe.lengthComputable) {
progressBar.max = pe.total
progressBar.value = pe.loaded
}
}
client.onloadend = function(pe) {
progressBar.value = pe.loaded
}
client.send()
二、進度事件(Progress Events)
Progress Events 定義了客戶端與伺服器通訊有關的事件。這些事件最早其實只針對XHR操作,但目前也被其它API借鑑。有以下6個進度事件。
(1)loadstart:在接收到相應資料的第一個位元組時觸發。
(2)progress:在接收相應期間持續不斷觸發。
(3)error:在請求發生錯誤時觸發。
(4)abort:在因為呼叫abort()方法而終止連結時觸發。
(5)load:在接收到完整的相應資料時觸發。
(6)loadend:在通訊完成或者觸發error、abort或load事件後觸發。
每個請求都從觸發 loadstart 事件開始,接下來是一或多個 progress 事件,然後觸發 error、abort 或 load 事件中的一個,最後以觸發 loadend 事件結束。
這些事件大都很直觀,但其兩個事件有一些細節需要注意。
1、load 事件
Firefox在實現XHR物件的某個版本時,曾致力於簡化非同步互動模型。最終,Firefox實現中引入了load事件,用以替代readystatechange事件。響應接收完畢後將觸發Load事件,因此也就沒有必要去檢查readyState屬性了。而onload事件處理程式會接收到一個event物件,其target屬性就指向XHR物件例項,因而可以訪問到XHR物件的所有方法和屬性。然而,並非所有瀏覽器都為這個事件實現了適當的事件物件。結果,開發人員還是要被迫使用XHR物件變數。
2、progress 事件
progress 事件會在瀏覽器接收新資料期間週期性地觸發。而 onprogress 事件處理程式會接收到一個 event 物件,其 target 屬性是XHR物件,但包含著三個額外的屬性:lengthComputable、loaded 和 total。
其中,lengthComputable是一個表示進度資訊是否可用的布林值,loaded表示已經接收的位元組數,total 表示根據 Content-Length 響應頭部確定的預期位元組數。
有了這些資訊,我們就可以為使用者建立一個進度指示器了。下面展示了為使用者建立進度指示器的一個示例。
var xhr = createXHR();
xhr.onload =function(){
if((xhr.status >=200&& xhr.status <300)|| xhr.status ==304){
alert(xhr.responseText);
}else{
alert("Request was unsuccessful: "+ xhr.status);
}
};
xhr.onprogress =function(event){
var divStatus = document.getElementById("status");
if(event.lengthComputable){
divStatus.innerHTML ="Recived"+event.loaded +" of "+event.total +" bytes";
}}
xhr.open("get","altevents.php",true);
xhr.send(null);
為確保正常執行,必須在呼叫 open() 方法之前新增 onprogress 事件處理程式。在前面的例子中,每次觸發 progress 事件,都會以新的狀態資訊更新HTML元素的內容。如果響應頭部中包含Content-Length欄位,那麼也可以利用此資訊來計算從響應中已經接收到的資料的百分比。
// 當請求型別為post時需要監聽xhr.upload。 // post 一般用來獲取上傳進度、get 用來獲取下載進度 xhr.upload.onprogress =function(e){
if(e.lengthComputable){ console.log(e.loaded / e.total *100)
}
}