H5 progress js結合實現動態進度條顯示小記
開通csdn好久了,出於工作原因,一直不能在網上記錄,但是終究覺得還是得留下些東西,所以開始整理筆記,調出可以記錄的描述一下,目的也是為了看到自己的成長,與大家共享。
今天這個是最近剛用過的,一直聽說H5的進度條標籤,一直也沒用過,這兩天剛好提出了需求,走起,小試一把,然後就記錄一下吧,其實還是蠻簡單的,重點就是建立好輪詢。
出於一些原因,有些地方我會用虛擬碼來標識。
第一步:就是在頁面裡寫好你想要進度展示的標籤,如果完全已知各種顯示樣式和情況,建議就直接寫在html裡,js控制顯隱就行,這樣比js插入dom要省些開銷。
<div id="loading" class="loading"> <div id="pre"> 正在檢測:<progress id="progressPre" /> </div> <div id="ready" class="hidden"> 開始下載: <progress id="progress" value="0" max="100" /> </div> <div id="noWay" class="hidden"> 無法下載! </div> </div>
第二步:在js裡利用ajax建立好輪詢機制,當然,可以用Comet和SSE,原理差不多,完全根據自己和實際的資源支援情況來定,我這邊就只能用ajax了。
因為要分別測試是否可下載,然後反饋下載進度或者無法下載,所以建立了兩次輪詢,一次負責輪詢是否可下載,一次負責進行下載進度反饋,這裡先把原理闡述,然後再貼程式碼。
第一次輪詢:將會像後臺詢問是否可下載,由於該步驟是通過查詢資料庫資料來實現,所以,一定一定不要輪詢太頻繁,否則頻繁連線資料庫,後果可能很嚴重(當然如果伺服器和資料庫很牛逼的,可以選擇性忽略,但是依然應該本著節約資源的原則開發,嗯是的),我這裡設定了3000ms輪詢一次,根據伺服器的反饋,這個頻率基本足夠,最多也就是2次就可以得到結果了。然而,這裡依然有個坑,就是用於輪詢反饋的欄位值,還是不要用0來標識了,因為貌似mysql在沒有值的時候(null),查詢返回前臺頁面的也是個0,我就被坑了,所有不管怎麼樣,儘量不要用0來標識。注意以上兩點,這部分就很簡單了, 寫好ajax,放入setInterval或者setTimeout鏈就可以了,在ajax的成功函式裡,根據返回值停止呼叫或者繼續呼叫。
第二次輪詢:如果可以下載,則進入第二次輪詢,查詢檔案下載進度;否則就沒有這一步了,直接反饋不可下載結束。這裡就說一下進度條<progress>了,有兩個屬性value和max,前者是當前完成的數值,後者是最大數值。所以不管你想進度什麼東西,都要確定這兩個資料,而且一定要匹配;如果是時間,就都用時間,如果是位元組,就都用位元組,否則會與實際情況不匹配。另外,如果你無法確定可以拿到這兩個資料,或者有一個無法拿到,那麼可能,就不能用了(這裡只是我針對這個標籤的結論,也許有大神會有其他方法)。一切如果無誤,則繼續ajax,建立輪詢,我這裡是下載檔案, 所有這次就只需要根據儲存檔案地址,不斷去輪詢檢視檔案大小,就知道當前檔案下載了多少,返回這個值,賦給value屬性,就可以在前臺看到進度條變化了。
虛擬碼如下:
第一次輪詢
var timer = setInterval/setTimeout(function a() {
ajax({
url:url,
data:data,
success:function(data){
if(dataright){
clearInterval(timer); //如果是setTimeout鏈,不需要這個。
doOtherTing get max value;
set max value to attr max;
start downloadTimer;
}else{
//如果用的是setTimeout鏈,這裡繼續呼叫setTimout,否則不用寫else
setTimout(a,3000)
}
}
})
}, 3000)
第二次輪詢
var downloadtimer = setInterval/setTimeout(function a() {
ajax({
url:url,
data:data,
success:function(data){
if(data < max){
set data to attr value
setTimout(a,3000) //如果用的是setTimeout鏈,這裡繼續呼叫setTimout
}else{
clearInterval(timer); //如果是setTimeout鏈,不需要這個else。
}
}
})
}, 1000)
如此一來,動態進度條就完成了。
總結一下要點:
1 . 寫好要顯示的progess標籤;
2. 根據實際需求建立輪詢機制,特別注意0值的問題,以及最大值和當前值的獲取問題;
3. 如果用定時器,建議setTimeout鏈,因為第一不需要手動清除,完事自己就停,第二,setInterval在js執行緒比較繁忙時,說白了,不能按既定時間來處理佇列的定時任務,有可能會跳過佇列中某一個已加入的任務;
4. 輪詢的次數一定要注意,根據伺服器和實際情況來確定,不可盲目頻繁進行,要為伺服器考慮哈;
5. 如果有大神有更好的方法,歡迎留言解惑,不勝感激