Workbox-background-sync

當您傳送資料至網路伺服器時,有時可能會失敗。這項服務 這可能是因為使用者失去連線,也可能是 伺服器停止運作;無論是哪種方法 可以再說一次

全新 BackgroundSync API 是解決問題的最佳解決方案當 Service Worker 偵測到 網路要求失敗,註冊接收 sync 事件, 當瀏覽器認為連線已恢復時,就會傳遞這個訊息。 請注意,即使在使用者離開 ,因此效果比傳統方法 重試失敗的要求。

Workbox 背景同步處理功能讓您可以更輕鬆地 BackgroundSync API,並將其用途與其他 Workbox 模組整合。這項服務 並針對尚未實作的瀏覽器,執行備用策略 BackgroundSync。

如果瀏覽器支援 BackgroundSync API,就會自動重播 代替您管理 由瀏覽器管理的間隔 在兩次重播之間 可能產生指數輪詢使用以下瀏覽器時, 並未原生支援 BackgroundSync API,Workbox 背景同步處理功能會將 自動重播。

基本用法

想要使用背景同步處理功能,最簡單的方法是使用會變更應用程式的 Plugin 自動將失敗的要求排入佇列,並在日後 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],
  }),
  'POST'
);

BackgroundSyncPlugin掛鉤 fetchDidFail 外掛程式回呼,以及 只有在擲回例外狀況時,系統才會叫用 fetchDidFail,這很可能是 導致網路故障這表示如果系統擷取到某個值 已收到回覆,並包含 4xx5xx 錯誤狀態。 如要重試所有產生的要求 (例如 5xx 狀態)。 方法是 新增 fetchDidSucceed 外掛程式 共同改善策略:

const statusPlugin = {
  fetchDidSucceed: ({response}) => {
    if (response.status >= 500) {
      // Throwing anything here will trigger fetchDidFail.
      throw new Error('Server error.');
    }
    // If it's not 5xx, use the response as-is.
    return response;
  },
};

// Add statusPlugin to the plugins array in your strategy.

進階用法

Workbox 背景同步處理功能也提供 Queue 類別,您可以 將失敗的要求例項化並新增至失敗的要求。失敗的要求會儲存 (位於 IndexedDB 中) 並在瀏覽器認為連線恢復時重試 (即 匯入同步處理事件時)。

建立佇列

如要建立工作箱背景同步佇列,您必須使用 佇列名稱 (在 origin):

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

const queue = new Queue('myQueueName');

佇列名稱會做為取得標籤的標記名稱的一部分 register() 版本 來自全球 SyncManager。是 也能做為 Object Store 名稱, 建立索引

將要求新增至佇列

建立佇列執行個體後,您可將失敗的要求新增至該執行個體。 您可以透過叫用 .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());
});

將要求加入佇列後,系統會在 Service Worker 收到 sync 事件 (在瀏覽器或 則表示連線恢復了)。如果瀏覽器不支援 BackgroundSync API 每次執行服務工作時,都會重試佇列 啟動。這需要控制 Service Worker 的網頁 所以成效有限

測試 Workbox 背景同步處理

不過在測試 BackgroundSync 時難免有直觀而困難

測試實作的最佳做法是:

  1. 載入網頁並註冊 Service Worker。
  2. 關閉電腦的網路或關閉網路伺服器。
    • 請勿使用 Chrome 離線版本。下拉式選單中的離線核取方塊 開發人員工具只會影響來自該網頁的要求。Service Worker 要求 繼續播放
  3. 使用 Workbox 背景同步功能發出應排入佇列的網路要求。
    • 如要確認要求已排入佇列,您可以查看 Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
  4. 現在請開啟網路或網路伺服器。
  5. 如要強制執行早期 sync 事件,請前往 Chrome DevTools > Application > Service Workers,輸入 workbox-background-sync:<your queue name><your queue name> 位置 您設定的佇列名稱,然後按一下「同步」按鈕。

    Chrome 開發人員工具中的「同步處理」按鈕範例

  6. 您應該會看到網路要求處理失敗的要求, 由於要求已 成功重播

類型

BackgroundSyncPlugin

實作 fetchDidFail 生命週期回呼的類別。如此一來 將失敗的要求加入背景同步佇列。

屬性

Queue

這個類別可管理在 IndexedDB 中儲存失敗的要求,以及進行重試 儲存和重播程序的所有部分都可以透過 回呼函式。

屬性

  • 建構函式

    void

    使用指定的選項建立佇列執行個體

    constructor 函式如下所示:

    (name: string, options?: QueueOptions) => {...}

    • 名稱

      字串

      這個佇列的專屬名稱。此名稱必須是 是專門用來登錄同步處理事件和儲存要求, 。如果發生以下情況,系統將擲回錯誤 就會偵測到重複的名稱。

    • 選項

      QueueOptions 選用

  • 名稱

    字串

  • getAll

    void

    傳回所有尚未過期的項目 (每個 maxRetentionTime)。 所有過期的項目都會從佇列中移除。

    getAll 函式如下所示:

    () => {...}

    • returns

      Promise&lt;QueueEntry[]&gt;

  • popRequest

    void

    移除並傳回佇列中的最後一個要求 (及 時間戳記與任何中繼資料)。傳回的物件採用以下格式: {request, timestamp, metadata}

    popRequest 函式如下所示:

    () => {...}

    • returns

      Promise&lt;QueueEntry&gt;

  • pushRequest

    void

    將傳送的要求儲存在 IndexedDB 中 (及其時間戳記和 中繼資料),

    pushRequest 函式如下所示:

    (entry: QueueEntry) => {...}

    • 項目

      QueueEntry

    • returns

      承諾<void>

  • registerSync

    void

    使用這個執行個體專屬的標記註冊同步處理事件。

    registerSync 函式如下所示:

    () => {...}

    • returns

      承諾<void>

  • replayRequests

    void

    反覆執行佇列中的每個要求,並嘗試重新擷取。 如果有任何要求無法重新擷取,系統會將其移回 佇列 (為下一個同步處理事件註冊重試)。

    replayRequests 函式如下所示:

    () => {...}

    • returns

      承諾<void>

  • shiftRequest

    void

    移除並傳回佇列中的第一個要求 (以及其 時間戳記與任何中繼資料)。傳回的物件採用以下格式: {request, timestamp, metadata}

    shiftRequest 函式如下所示:

    () => {...}

    • returns

      Promise&lt;QueueEntry&gt;

  • 大小

    void

    傳回佇列中的項目數量。 請注意,過期項目 (依maxRetentionTime) 也包括在內。

    size 函式如下所示:

    () => {...}

    • returns

      Promise&lt;number&gt;

  • unshiftRequest

    void

    將傳送的要求儲存在 IndexedDB 中 (及其時間戳記和 。

    unshiftRequest 函式如下所示:

    (entry: QueueEntry) => {...}

    • 項目

      QueueEntry

    • returns

      承諾<void>

QueueOptions

屬性

  • forceSyncFallback

    布林值 選填

  • maxRetentionTime

    編號 選填

  • OnSync

    OnSyncCallback 選用

QueueStore

一種類別,用於管理 IndexedDB 中佇列儲存要求。 並以佇列名稱編入索引,以便更方便存取

大部分的開發人員不需要直接存取這個類別; 但適合進階用途

屬性

  • 建構函式

    void

    建立這個執行個體與佇列執行個體的關聯,讓新增的項目可以 以藉由佇列名稱識別

    constructor 函式如下所示:

    (queueName: string) => {...}

    • queueName

      字串

  • deleteEntry

    void

    刪除指定 ID 的項目。

    警告:這個方法不會確保刪除的項目屬於此情況 佇列 (即與 queueName 相符)。不過,這類限制是可以接受的 因為這個類別不會公開進行額外檢查 這個方法會比執行速度更快

    deleteEntry 函式如下所示:

    (id: number) => {...}

    • id

      數字

    • returns

      承諾<void>

  • getAll

    void

    傳回儲存庫中與 queueName 相符的所有項目。

    getAll 函式如下所示:

    () => {...}

    • returns

      Promise&lt;QueueStoreEntry[]&gt;

  • popEntry

    void

    移除並傳回佇列中與 queueName 相符的最後一個項目。

    popEntry 函式如下所示:

    () => {...}

    • returns

      Promise&lt;QueueStoreEntry&gt;

  • pushEntry

    void

    附加佇列中的最後一個項目。

    pushEntry 函式如下所示:

    (entry: UnidentifiedQueueStoreEntry) => {...}

    • 項目

      UnidentifiedQueueStoreEntry

    • returns

      承諾<void>

  • shiftEntry

    void

    移除並傳回佇列中與 queueName 相符的第一個項目。

    shiftEntry 函式如下所示:

    () => {...}

    • returns

      Promise&lt;QueueStoreEntry&gt;

  • 大小

    void

    傳回儲存庫中與 queueName 相符的項目數量。

    size 函式如下所示:

    () => {...}

    • returns

      Promise&lt;number&gt;

  • unshiftEntry

    void

    請先在佇列中前置一個項目。

    unshiftEntry 函式如下所示:

    (entry: UnidentifiedQueueStoreEntry) => {...}

    • 項目

      UnidentifiedQueueStoreEntry

    • returns

      承諾<void>

StorableRequest

類別,方便將要求序列化與還原序列化,使要求 可能會出現在 IndexedDB 中

大部分的開發人員不需要直接存取這個類別; 但適合進階用途

屬性

  • 建構函式

    void

    接受可用於建構模型的要求資料物件 Request,但也可以儲存在 IndexedDB 中。

    constructor 函式如下所示:

    (requestData: RequestData) => {...}

    • requestData

      RequestData

      要求資料的物件,其中包含 url 加上下列任何相關屬性: [requestInit]https://fetch.spec.whatwg.org/#requestinit

  • clone

    void

    建立並傳回執行個體的深度複製。

    clone 函式如下所示:

    () => {...}

  • toObject

    void

    傳回例項 _requestData 物件的深度複製。

    toObject 函式如下所示:

    () => {...}

    • returns

      RequestData

  • toRequest

    void

    將此例項轉換為要求。

    toRequest 函式如下所示:

    () => {...}

    • returns

      要求

  • fromRequest

    void

    將 Request 物件轉換為可結構化的純物件 複製或 JSON 字串。

    fromRequest 函式如下所示:

    (request: Request) => {...}

    • 申請。

      要求