1. 程式人生 > 其它 >AJAX 資料傳輸進度條設計與實現_qingyafan的部落格

AJAX 資料傳輸進度條設計與實現_qingyafan的部落格

AJAX 無疑是主流的客戶端和伺服器端通訊的方式,AJAX 通訊方式當然有很多優點,但是缺點也一定程度上是由優點造成的,因為AJAX 通訊過程中,頁面不會全域性重新整理,這在傳輸的資料量比較小且網速比較好的時候,是沒有什麼問題的,但是當資料量比較大的時候,頁面就會長時間沒有任何反應,可能讓使用者誤以為請求失敗,所以在資料傳輸沒有完成的等待時間內,我們以一個進度條或者緩衝環給使用者以正在通訊的視覺化效果,這樣使用者體驗就會大大提升。

那麼怎麼實現呢?我們首先來看看 AJAX 的通訊原理。

一、 AJAX 通訊原理

  W3C 一個工作草案規定了 Progress Event,定義了與客戶端和伺服器通訊有關的事件。這些事件最初只是針對 AJAX 操作,現在其他的 API 也開始借鑑。主要進度事件有六個:
  • loadstart,當接收到伺服器相應的第一個位元組時觸發;
  • progress,在接收資料期間不斷的觸發;
  • error,當請求發生錯誤時觸發;
  • abort,呼叫 abort 函式時觸發;
  • load,接收資料完成時觸發;
  • loadend,整個通訊過程完成後觸發。

這些事件各個瀏覽器的支援程度如何呢?我們可以看一幅圖:

  目前,PC 瀏覽器只有 IE 不支援這些事件的所有實現,但是並不影響我們要使用的事件,Opera Mini 是針對手機的 Opera 瀏覽器,用的並不多。根據現在的支援程度,我們可以使用 Progress Events 實現一些應用,比如本文要實現的進度條。

  本文要實現的“進度條”直接用到的事件是 `progress` 事件,各個瀏覽器都支援,是由 Mozilla 引入的革新。該事件觸發時,事件處理程式會接收一個事件物件 event,該事件物件包含四個我們要用到的屬性:
  • target,對應的 XHR 物件;

  • lengthComputable,表示進度資訊是否可用的布林值;

  • loaded,已經接收的位元組數;

  • total,響應資料的預期總位元組數,根據 Content-Length 響應頭部確定。

    這樣我們通過監聽 progress 事件,檢視 position 的值與 total 的比值,就能確定接收資料的百分比,通過進度條顯示,即可完成預期效果。

二、 實現


注:
1、例子相容 IE 9+
2、使用了JQuery 和 Bootstrap 進度條


2.1 HTML 頁面

  首先我們編輯 HTML 頁面,頁面中包含一個 bootstrap 進度條,同時包含一個按鈕,用以觸發請求資料,並同時修改進度條進度。HTML 頁面主要部分實現如下:
<div class="progress">
    <div id="pros" class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
    </div>
</div>
<button id="trigger_ajax" type="button" >請求資料</button>
  控制進度條的已完成進度是 `id="pros"` 的 DIV 的 width 屬性,在進度條上顯示的進度文字,是 DIV 內含的文字 `text`,我們通過改變這兩個屬性,就可以實現進度的動態變化。

2.2 AJAX 請求

我們給按鈕繫結點選事件,用來請求伺服器端的資料:

var trigger = document.getElementById("trigger_ajax");
trigger.onclick = function(){
    var xhr = new XMLHttpRequest();
    xhr.onprogress = function(event){
        if(event.lengthComputable){
            var loaded = parseInt(event.loaded/event.total*100)+"%";
            $('#pros').width(loaded);
            $('#pros').text(loaded);
        }
    }
    xhr.open("post", "for_test.php", true);
    xhr.send(null);
}

注意,progress 事件要在 open 之前繫結,如果 event.lengthComputable 返回結果為 ture,那麼就根據伺服器的返回資料狀態改變進度條的狀態:

if(event.lengthComputable){
    var loaded = parseInt(event.loaded/event.total*100)+"%";
    $('#pros').width(loaded);
    $('#pros').text(loaded);
}

2.3 伺服器端返回資料

  最後我們要寫出伺服器端的程式碼,我使用的 PHP ,有一點需要注意,伺服器端的程式碼過程要“返回結果比較大,傳輸需要一段時間”,我們寫一個比較大的迴圈,組成一個非常長的字串,然後返回這個字串:
<?php 
    $results="";
    for($i=1; $i<=900000; $i++){
        $results.='"'.$i.'"';
    }
    $len = strlen($results);
    header("Content-Length: $len");
    echo $results;
?>
  注意到 `header("Content-Length: $len");`,寫出 http 頭時候,附加 “Content-Length”,這樣 JS 端的 progress 事件的 event.lengthComputable 值才會為 `true`, event.total 才會在資料傳輸完畢之前取得值,否則 event.lengthComputable 值會返回 `false`, event.total 在資料完成之前值都是 `0`。

最後,我們執行頁面,可以看到:

三、 總結

  我們可以把這個進度條應用在請求資料量比較大的情境中,在傳輸資料的過程中給使用者以直觀的視覺感知,這樣會提升使用者的體驗。或者應用在網路較差的情況下,請求時間可能會較長,當用戶觸發網路請求後,彈出一個包含進度條的彈出框,當請求完畢後,彈出框自動消失。

當然,表示進度,並不一定要使用條形,我們可以換成 環形等形狀,大致的原理都是一樣的,將後臺返回的進度動態改變前臺的緩衝進度。

當我們必須要在不支援 progress 事件的瀏覽器中實現類似功能時,我們可以利用所有瀏覽器都支援 AJAX 這個特性,請求開始和請求成功都有明確的時間點,我們退而求其次,不使用有刻度的進度條,而使用一個緩衝環,在請求完成之前,一直處於緩衝狀態。

這樣,至此為止,我們考慮了支援所有瀏覽器的 AJAX 請求進度顯示,和各個形狀的進度條。

OK,就寫到這裡吧!有什麼問題可以部落格下留言評論。

本文轉自 https://blog.csdn.net/qingyafan/article/details/49049061?spm=1001.2014.3001.5502,如有侵權,請聯絡刪除。