恢復連線後重試要求

向網路伺服器發出要求時,可能會失敗。這可能是因為使用者連線中斷,或遠端伺服器已停止運作。

雖然本說明文件的重點在於處理 Service Worker 中的 GET 要求,但 POSTPUTDELETE 等其他方法或許就能派上用場。這些方法通常用於與後端 API 通訊,以提供網頁應用程式的資料。如果這些要求在沒有 Service Worker 的情況下失敗,使用者必須在恢復連線時手動重試,而且使用者不一定會記得。

如果這個情況描述您的應用程式,而且同屬一個服務工作處理程序,建議您在使用者恢復連線後,再重試傳送失敗的要求。BackgroundSync API 提供此問題的解決方案。當服務工作處理程序偵測到失敗的網路要求時,可在瀏覽器偵測到連線傳回時註冊以接收 sync 事件。即使使用者離開註冊事件的網頁,系統也可能會傳送 sync 事件,讓回應效率比重試失敗要求的其他方法更有效。

Workbox 利用 workbox-background-sync 模組簡化這個 API,讓 BackgroundSync API 能更容易與其他 Workbox 模組搭配使用。並針對尚未支援 BackgroundSync 的瀏覽器實作備用策略。

基本用法

BackgroundSyncPlugin 會從 workbox-background-sync 模組匯出,可用於將失敗的要求排入佇列,並在日後 sync 事件觸發時重試:

import {BackgroundSyncPlugin} from 'workbox-background-sync';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

const bgSyncPlugin = new BackgroundSyncPlugin('myQueueName', {
  maxRetentionTime: 24 * 60 // Retry for max of 24 Hours (specified in minutes)
});

registerRoute(
  /\/api\/.*\/*.json/,
  new NetworkOnly({
    plugins: [bgSyncPlugin]
  }),
  // An optional third parameter specifies the request method
  'POST'
);

此處,BackgroundSyncPlugin 會套用到符合 POST 要求的路徑,到擷取 JSON 資料的 API 路徑。如果使用者處於離線狀態,BackgroundSyncPlugin 會在使用者恢復連線時重試要求,但最多只會顯示一天的時間。

進階用法

workbox-background-sync 也提供 Queue 類別,可讓您例項化並將失敗的要求例項化。和 BackgroundSyncPlugin 的情況一樣,失敗的要求會儲存在「IndexedDB」IndexedDB中,並在瀏覽器認為連線恢復時嘗試嘗試。

建立一個佇列

如要建立佇列,請使用代表佇列名稱的字串將 Queue 物件執行個體化:

import {Queue} from 'workbox-background-sync';

const queue = new Queue('myQueueName');

透過全域 SyncManager 提供的 register() 方法建立,系統會將佇列名稱做為標記名稱的一部分。同時也是索引資料庫提供的 Object Store 名稱。

將要求加入佇列

建立 Queue 執行個體後,您可以使用該執行個體的 pushRequest() 方法,將失敗的要求新增至該執行個體:

import {Queue} from 'workbox-background-sync';

const queue = new Queue('myQueueName');

self.addEventListener('fetch', (event) => {
  // Add in your own criteria here to return early if this
  // isn't a request that should use background sync.
  if (event.request.method !== 'POST') {
    return;
  }

  const bgSyncLogic = async () => {
    try {
      const response = await fetch(event.request.clone());
      return response;
    } catch (error) {
      await queue.pushRequest({request: event.request});
      return error;
    }
  };

  event.respondWith(bgSyncLogic());
});

將要求新增至佇列後,服務工作站收到 sync 事件時,就會自動重試,因為瀏覽器認為網路已可供使用。如果是不支援 BackgroundSync API 的瀏覽器,每次服務工作處理程序啟動時,就會重試要求,較不有效重試失敗的要求,但是採取其他排序方法。

正在測試 workbox-background-sync

測試背景同步處理行為並不容易,但可以透過 Chrome 開發人員工具完成。目前的最佳做法如下:

  1. 載入註冊 Service Worker 的頁面。
  2. 關閉電腦的網路連線,或關閉網路伺服器。請勿使用 Chrome 開發人員工具中的離線切換鈕!離線核取方塊只會影響來自網頁的要求,但 Service Worker 要求會繼續執行。
  3. 使用 workbox-background-sync 發出應排入佇列的網路要求。如要查看已排入佇列的要求,您可以查看 Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
  4. 現在請恢復網路連線或重新開啟網路伺服器。
  5. 前往 Chrome DevTools > Application > Service Workers 強制執行 sync 早期事件。輸入 workbox-background-sync:<your queue name> 的標記名稱,其中 <your queue name> 是您設定的佇列名稱。
  6. 按一下「同步」按鈕。
    Chrome 開發人員工具應用程式面板中的背景同步處理公用程式螢幕截圖。為「myQueueName」佇列指定的同步處理事件「workbox-background-sync」這項指令後續課程我們將逐一介紹
預先訓練的 API、AutoML 和自訂訓練
  7. 現在您應該會看到先前失敗的網路要求重試,並完成處理。因此,由於重新發出要求成功,因此 IndexedDB 儲存庫應是空的。

結論

使用 workbox-background-sync 重試失敗的網路要求,是改善應用程式的使用者體驗和可靠性的好方法,例如讓使用者重新提交失敗的 API 要求,以免遺失要傳送至 API 的資料。也能用來填補自有資料 (例如數據分析) 的資料缺口。事實上,workbox-google-analytics 模組會透過 workbox-background-sync 重新嘗試將失敗的資料傳送至 Google Analytics 的要求。

無論您的用途為何,workbox-background-sync 都能簡化這類工作,提升開發人員體驗,並讓您有更多機會改善網頁應用程式的使用者體驗和功能。