iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0

嗨大家好,我是Eric。當談到API請求,我們通常會使用fetch、axios等現代的方法,但有一個我們可能忽略的功能,是由傳統的XHR(XMLHttpRequest)提供的,那就是能夠監聽請求和響應的進度。

對於 User 來說,這個功能特別有用,尤其是在上傳或下載大文件的時候,可以使用XHR來實現進度條可以顯著提升用戶體驗,接下來讓我們來了解一下XHR到底是什麼吧~

什麼是進度監聽器?

進度監聽器是一種用於監聽 HTTP 請求進度的技術。它允許開發人員實時監控請求的進度,例如文件下載或上傳時的進度,並在需要時執行相應的處理。

  • xhr 可監聽 請求/響應的進度監控
  • fectch 只能監聽響應的數據

使用 XMLHttpRequest 物件

在 JavaScript 中,我們可以使用 XMLHttpRequest (XHR) 物件來進行網路請求,並通過添加監聽器來監控進度。

進度相關的事件

XHR 物件提供了一些與進度相關的事件,包括:

  • loadstart: 請求開始時觸發。
  • progress: 進度更新時觸發,通常用於顯示下載或上傳進度。
  • load: 下載完成時觸發,表示請求成功完成並收到了完整的回應。
  • loadend: 下載完成後觸發,表示請求已經結束,不論成功或失敗。
  • error: 當請求發生錯誤時觸發,例如網絡錯誤或服務器錯誤。
  • abort: 當請求被取消時觸發,例如使用 xhr.abort() 方法取消請求。
  • timeout: 當請求超時時觸發,可以在 xhr.timeout 屬性中設置請求的超時時間。

添加進度監聽器

我們可以使用 xhr.addEventListener() 方法來添加進度監聽器,並在事件觸發時執行相應的處理。

javascriptCopy code
// 定義進度監聽器
function updateProgress(event) {
  // 檢查是否能計算進度
  if (event.lengthComputable) {
    // 計算進度百分比
    let progress = (event.loaded / event.total) * 100;
    console.log('下載進度: ' + progress + '%');
  } else {
    // 當無法計算進度時,例如檔案大小未知,無法顯示進度
    console.log('無法計算進度');
  }
}

// 創建 XMLHttpRequest 物件並添加 Progress 監聽器
let xhr = new XMLHttpRequest();
xhr.addEventListener('loadstart', function() {
  console.log('請求開始');
});

xhr.addEventListener('progress', updateProgress, false);

xhr.addEventListener('load', function() {
  console.log('請求完成');
});

xhr.addEventListener('error', function() {
  console.log('請求失敗');
});

xhr.addEventListener('abort', function() {
  console.log('請求被取消');
});

// 發送請求
$('#uploadBtn').click(function () {
	$.ajax({
          url: 'http://192.168.50.154:8115/Api/DashboardDataAnalysis/CivilAircraftCount', // 請將 'your_api_endpoint' 替換為實際的 API 請求地址
          type: 'POST', // 請指定請求方法
          // async: true,
          contentType: 'application/json',
          data: JSON.stringify({
            SystemParameter: 'xxx',
            Token:
              'xxx',
            Account: 'xxx',
            Name: 'xxx',
            Role: '1',
          }),
          xhr: function () {
            // 創建 XMLHttpRequest 物件並添加 Progress 監聽器
            let xhr = new window.XMLHttpRequest()

            // 添加 upload 屬性後不管是上傳還是下載都可以監聽
            xhr.upload.addEventListener('progress', updateProgress, false) // 表示事件處理程序在事件冒泡階段被觸發(預設情況下,事件處理程序在事件捕獲階段被觸發)
            xhr.addEventListener('load', transferComplete, false)
            xhr.addEventListener('error', transferFailed, false)
            xhr.addEventListener('abort', transferCanceled, false)
            return xhr
          },
          success: function (response) {
            console.log('成功', response)
          },
          error: function (error) {
            console.log('失敗', error)
          },
        })
      })

這個進度監聽器會在請求開始時觸發 loadstart 事件,並在進度更新時觸發 progress 事件,其中 updateProgress 函式會計算並顯示下載進度百分比。當請求完成時,會觸發 load 事件,如果請求失敗則會觸發 error 事件,如果請求被取消則會觸發 abort 事件。最後,在請求結束時(無論成功或失敗)都會觸發 loadend 事件。

進度計算

進度監聽器通常用於顯示請求的進度,特別是在文件上傳或下載時。為了計算進度,我們需要了解以下屬性:

  • event.lengthComputable: 一個布林值,表示是否能計算進度。如果為 true,則表示能夠計算進度;如果為 false,則表示進度無法計算,例如檔案大小未知。
  • event.loaded: 表示已經下載或上傳的字節數。
  • event.total: 表示總共需要下載或上傳的字節數。

根據這些屬性,我們可以計算進度百分比,如下所示:

function updateProgress(event) {
  if (event.lengthComputable) {
    let progress = (event.loaded / event.total) * 100;
    console.log('下載進度: ' + progress + '%');
  } else {
    console.log('無法計算進度');
  }
}

文件上傳進度

當使用者進行文件上傳時,進度監聽器可以幫助我們實時顯示上傳進度,讓用戶了解文件上傳的狀態。

// HTML 檔案上傳表單
<input type="file" id="fileInput" />
<button onclick="uploadFile()">上傳文件</button>

// 定義事件監聽的回調函式
function updateProgress(event) {
  if (event.lengthComputable) {
    let progress = (event.loaded / event.total) * 100;
    console.log('上傳進度: ' + progress + '%');
  } else {
    console.log('無法計算進度');
  }
}

function transferComplete(event) {
  console.log('文件上傳完成');
}

function transferFailed(event) {
  console.log('文件上傳失敗');
}

function transferCanceled(event) {
  console.log('文件上傳已被取消');
}

function uploadFile() {
	// 獲取文件輸入元素和文件
  let fileInput = document.getElementById('fileInput');
  let file = fileInput.files[0];

  // 使用 FormData 將文件添加到請求中
  let formData = new FormData();
  formData.append('file', file);

  // 創建 XMLHttpRequest 物件
  let xhr = new XMLHttpRequest();

  // 添加進度監聽器和其他事件處理程序
  xhr.upload.addEventListener('progress', updateProgress, false);
  xhr.addEventListener('load', transferComplete, false);
  xhr.addEventListener('error', transferFailed, false);
  xhr.addEventListener('abort', transferCanceled, false);

		// 請求 api
    $.ajax({
			code...
		)}
}

// 當按鈕被點擊時,觸發上傳文件的函數
document.getElementById('uploadBtn').addEventListener('click', uploadFile);

請求超時處理

有時候,請求可能因為網絡問題或服務器問題而長時間未響應,進而造成應用程式無法繼續運行。為了處理這種情況,我們可以添加請求超時機制。

xhr.timeout = 5000; // 設定請求超時時間(毫秒為單位)
xhr.ontimeout = function() {
  console.log('請求超時');
  // 可以在這裡執行相應的處理,例如顯示錯誤訊息或重試請求
};

結論

進度監聽器不僅僅用於文件上傳或下載,它還可以應用於其他場景,例如:

  • 文件下載進度:當用戶下載大型文件時,可以使用進度監聽器來顯示下載
    謝謝大家~~~明天見!

參考網站推薦:
xhr:https://www.gushiciku.cn/pl/ay1L/zh-hk
fecth:https://zh.javascript.info/fetch-progress


上一篇
Day5 - 函數應用- 併發任務
下一篇
Day7 - 物件陣列去重
系列文
JavaScript 是什麼?可以吃嗎?20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言