天天看點

原生支援bgFetch?大檔案下載下傳這麼玩?

作者:前端進階進階

大家好,很高興又見面了,我是"進階前端‬進階‬",由我帶着大家一起關注前端前沿、深入前端底層技術,大家一起進步,也歡迎大家關注、點贊、收藏、轉發!

Background Fetch簡稱bgFetch。

1.為什麼是Background Fetch?

原生支援bgFetch?大檔案下載下傳這麼玩?

深入了解浏覽器Background Fetch。 Created by Decipher Zone Softwares

1.1 為什麼要Background Fetch?

當 Web 應用程式需要下載下傳大檔案時,例如電影、音頻檔案和軟體,通常可能會出現問題,因為使用者需要保持與頁面的連接配接才能完成下載下傳。 如失去連接配接,關閉頁籤等任務将停止。

原生支援bgFetch?大檔案下載下傳這麼玩?

為什麼要Background Fetch?From:istockphoto

Background Synchronization 為 service workers 提供了一種延遲處理直到使用者連接配接的方法。但是不能用于長時間運作的任務,例如下載下傳大檔案。 同時,要求 service worker 在完成之前保持活動狀态,因為為了節省電池壽命、防止在背景發生不需要的任務,浏覽器将在某個時候終止任務。

1.2 Background Fetch解決了什麼痛點?

Background Fetch API 解決了這個問題。 它為 Web 開發人員建立了一種方式,讓浏覽器在背景執行一些操作,例如,當使用者單擊按鈕下載下傳視訊檔案時。 然後浏覽器以使用者可見的方式執行提取,顯示進度、提供取消下載下傳的方法。 下載下傳完成後,浏覽器會打開 Service Worker,此時應用程式可以根據需要對響應執行某些操作。

如果使用者在離線時啟動程序,背景提取 API 将啟用提取。 一旦連接配接起來,它就會開始。 如果使用者下線,該過程将暫停,直到使用者再次上線。

2.Background Fetch如何工作?

Background Fetch工作流程如下:

  • 告訴浏覽器在背景執行一組fetch。
  • 浏覽器調用fetch,向使用者顯示進度。
  • 一旦擷取完成或失敗,浏覽器就會打開service workers并觸發一個事件來告訴你發生了什麼,由開發者決定如何處理響應。

如果使用者在第 1 步後關閉了站點的頁面,下載下傳将繼續。

fetch是高度可見的并且很容易中止,是以不存在太長的背景同步任務的隐私問題。 而且service worker 也不會持續運作,是以不用擔心濫用系統,例如在背景挖礦。

在某些平台(例如 Android)上,浏覽器可能會在第 1 步後關閉,因為浏覽器可以将fetch操作交給作業系統。如果使用者在離線時開始下載下傳,或者在下載下傳過程中離線,背景fetch将暫停并稍後恢複。

3.浏覽器相容

3.1 特征檢測

與任何新功能一樣,需要檢測浏覽器是否支援它。 對于 Background Fetch,可以通過如下代碼快速檢測:

if ('BackgroundFetchManager' in self) {
  //浏覽器支援Background Fetch!
}           

從caniuse的資料來看,該API的浏覽器整體支援率達到了73.58%。Chrome從74版本開始,Edge從79版本開始都已經支援Background Fetch。不過,可惜的是,FireFox和Safari目前支援并不好。

原生支援bgFetch?大檔案下載下傳這麼玩?

3.2 執行個體化Background Fetch

使用 Background Fetch 需要注冊一個 service worker。 然後調用 backgroundFetch.fetch() 來執行,同時傳回一個Promise。

Background Fetch提取可能會請求多個檔案。 在下面的示例中,請求了 MP3 和 JPEG。

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.fetch(
    // service worker的fetch方法
    "my-fetch",
    ["/ep-5.mp3", "ep-5-artwork.jpg"],
    // 請求MP3和JPEG
    {
      title: "Episode 5: Interesting things.",
      icons: [
        {
          sizes: "300x300",
          src: "/ep-5-icon.png",
          type: "image/png",
        },
      ],
      downloadTotal: 60 * 1024 * 1024,
    }
  );
});
           

3.3 擷取已有的Background Fetch

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});           

通過傳遞Background Fetch的id來擷取, 如果沒有使用該 ID 的Background Fetch,則傳回 undefined。

Background Fetch從它被注冊的那一刻起就被認為是“活躍的”,直到它成功、失敗或被終止。可以使用 getIds 擷取所有活動Background Fetch的清單:

navigator.serviceWorker.ready.then(async (swReg) => {
  const ids = await swReg.backgroundFetch.getIds();
});           

3.4 跟蹤Background Fetch進度

可以通過進度事件來完成。請記住,downloadTotal可以是任何值,未提供,則為 0。

bgFetch.addEventListener('progress', () => {
  // If we didn't provide a total, we can't provide a %.
  if (!bgFetch.downloadTotal) return;
  const percent = Math.round(bgFetch.downloaded / bgFetch.downloadTotal * 100);
  console.log(`Download progress: ${percent}%`);
});           

3.5 擷取請求和響應

bgFetch.match('/ep-5.mp3').then(async (record) => {
  if (!record) {
    console.log('No record found');
    return;
  }

  console.log(`Here's the request`, record.request);
  const response = await record.responseReady;
  console.log(`And here's the response`, response);
});           
在 Chrome 目前的實作中,您隻能在 backgroundfetchsuccess、backgroundfetchfailure 和 backgroundfetchabort service worker 事件期間擷取請求和響應(見下文)

4.本文總結

本文主要和大家介紹浏覽器的新特性Background Fetch,因為Background Fetch本身的複雜性,文章沒有過多的展開。但是文末的參考資料提供了大量優秀文檔以供學習,如果有興趣可以自行閱讀。如果大家有什麼疑問歡迎在評論區留言。

參考資料

https://developer.mozilla.org/en-US/docs/Web/API/Background_Fetch_API

https://caniuse.com/?search=Background%20Fetch

https://developer.chrome.com/blog/background-fetch/

繼續閱讀