背景同步簡介

Jake Archibald
Jake Archibald

背景同步處理是新的網路 API,可讓您在使用者連線穩定前,暫緩執行動作。這可確保使用者要傳送的內容確實傳送出去。

問題

網際網路是消磨時間的好地方,我們不會浪費時間在網路上搜尋,貓咪不喜歡花朵變色龍喜歡泡泡,或是Eric Bidelman90 年代末的推桿高爾夫英雄

但有時,我們不想浪費時間。理想的使用者體驗應類似於:

  1. 手機從口袋中拿出。
  2. 達成次要目標。
  3. 手機放回口袋。
  4. 繼續生活。

不幸的是,這項體驗經常因連線不佳而中斷。我們都曾經歷過這種情況。你盯著空白畫面或旋轉圖示,知道自己應該放棄並繼續生活,但還是再等 10 秒,以防萬一。10 秒後?不會發生任何事情。

但為何要放棄?你已經花費時間,如果什麼都沒有就離開,那就太浪費了,所以你繼續等待。到這個時候,你「想」放棄,但你知道,只要你放棄,就會錯過所有內容載入前的那一秒鐘。

服務工作者可解決網頁載入問題,讓您從快取提供內容。但如果網頁需要傳送內容給伺服器,該怎麼辦呢?

目前,如果使用者按下訊息的「傳送」按鈕,就必須一直盯著旋轉圖示,直到傳送作業完成為止。如果使用者嘗試離開或關閉分頁,我們會使用 onbeforeunload 顯示類似「不,我需要你再盯著這個旋轉圖示看一會兒」的訊息。抱歉」;如果使用者沒有連線,我們會告訴使用者:「很抱歉,必須稍後再試一次。」

這根本是胡說八道。背景同步處理功能可讓您更有效率。

解決方案

以下影片為 Emojoy 的表情符號專用聊天示範。這是一個漸進式網頁應用程式,採用離線優先的運作方式。應用程式會使用推播訊息和通知,並使用背景同步功能。

如果使用者在完全無法連線時嘗試傳送訊息,系統會在使用者恢復連線後在背景傳送訊息。

自 2016 年 3 月起,Chrome 49 以上版本提供背景同步處理功能。如要查看實際運作情形,請按照下列步驟操作:

  1. 開啟 Emojoy
  2. 離線 (使用飛航模式或前往當地的法拉第籠)。
  3. 輸入訊息。
  4. 返回主畫面 (視需要關閉分頁或瀏覽器)。
  5. 連上網路。
  6. 訊息會在背景傳送!

這樣一來,您就能在背景傳送資料,進而提升效能。應用程式不需要特別處理訊息傳送作業,因此可以立即將訊息加入輸出內容。

如何要求背景同步

在真正的可擴充網頁樣式中,這是一項低階功能,可讓您自由執行所需的操作。您要求在使用者連上網路時觸發事件,如果使用者已連上網路,則會立即觸發。接著,您可以監聽該事件,並執行所需的操作。

與推播訊息一樣,這項功能會使用 Service Worker 做為事件目標,讓這項功能在網頁未開啟時運作。如要開始,請透過網頁註冊同步處理:

// Register your service worker:
navigator.serviceWorker.register('/sw.js');

// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
  return swRegistration.sync.register('myFirstSync');
});
 ```

Then listen for the event in `/sw.js`:

```js
self.addEventListener('sync', function(event) {
  if (event.tag == 'myFirstSync') {
    event.waitUntil(doSomeStuff());
  }
});

大功告成!在上述情況中,doSomeStuff() 應傳回承諾,指出嘗試執行的動作是否成功/失敗。如果傳回承諾,表示同步處理已完成。如果失敗,系統會安排另一次同步作業。重試同步作業也會等待連線,並採用指數輪詢。

同步作業的標記名稱 (上例中的「myFirstSync」) 在特定同步作業中不得重複。如果您使用與待處理同步作業相同的標記註冊同步作業,系統會將該作業與現有的同步作業合併。也就是說,您可以為每次使用者傳送郵件註冊「清空收件匣」同步作業,但如果使用者在離線時傳送 5 封郵件,您只會在他們上線時收到一次同步作業。如要 5 個獨立的同步處理事件,請使用專屬代碼!

以下是簡單的示範,只會執行最基本的工作,使用同步處理事件顯示通知。

我可以將背景同步處理功能用於哪些情況?

理想情況下,您應該使用這項功能,安排在網頁生命週期結束後傳送您重視的任何資料。即時通訊訊息、電子郵件、文件更新、設定變更、相片上傳內容... 凡是您希望傳送至伺服器的內容,即使使用者離開或關閉分頁,也能傳送。網頁可將這些內容儲存在 indexedDB 中的「outbox」儲存庫中,Service Worker 會擷取這些內容並傳送。

不過,您也可以使用它擷取少量資料...

另一個示範!

這是我為超級充電網頁載入建立的離線維基百科示範。我已在其中加入一些背景同步功能。

親自試試看。請確認你使用的是 Chrome 49 以上版本,然後執行下列操作:

  1. 開啟任一文章,例如 Chrome
  2. 離線 (使用飛航模式或加入像我一樣糟糕的行動網路供應商)。
  3. 點選其他文章的連結。
  4. 系統應會通知您網頁無法載入 (如果網頁只是需要一些時間載入,也會顯示這則訊息)。
  5. 同意接收通知。
  6. 關閉瀏覽器。
  7. 切換為線上狀態
  8. 系統會在文章下載完畢、快取完成且可供查看時通知你!

使用者只要採用這個模式,就能將手機放入口袋,繼續過著自己的生活,因為他們知道手機會在擷取所需內容時發出通知。

權限

我展示的示範使用 網頁通知,需要權限,但背景同步本身不需要。

同步處理事件通常會在使用者開啟網站頁面時完成,因此要求使用者授權會導致使用者體驗不佳。我們會限制同步作業的註冊和觸發時間,以防濫用。例如:

  • 只有在使用者開啟網站視窗時,您才能註冊同步處理事件。
  • 事件執行時間有上限,因此您無法使用這些事件每隔 x 秒對伺服器執行 ping 作業、挖掘比特幣或執行其他作業。

當然,這些限制可能會根據實際使用情況而放寬或收緊。

漸進增強

所有瀏覽器都支援背景同步功能還需要一段時間,尤其是 Safari 和 Edge 尚未支援服務工作者。不過,漸進式改善功能在這裡很有幫助:

if ('serviceWorker' in navigator && 'SyncManager' in window) {
  navigator.serviceWorker.ready.then(function(reg) {
    return reg.sync.register('tag-name');
  }).catch(function() {
    // system was unable to register for a sync,
    // this could be an OS-level restriction
    postDataFromThePage();
  });
} else {
  // serviceworker/sync not supported
  postDataFromThePage();
}

如果無法使用服務工作者或背景同步功能,請按照目前的方式,從網頁發布內容。

即使使用者似乎擁有良好的連線品質,仍建議使用背景同步功能,因為這可避免在傳送資料期間發生導覽和分頁關閉的情況。

未來

我們預計在 2016 上半年將背景同步功能納入穩定版 Chrome,同時開發「定期背景同步」的變化版本。透過定期背景同步處理功能,您可以要求以時間間隔、電池狀態和網路狀態為限制的事件。當然,這需要使用者授權,且瀏覽器也會決定這些事件的觸發時機和頻率。換句話說,新聞網站可以要求每小時同步處理一次,但瀏覽器可能知道您只會在 7 點閱讀該網站,因此會在每天 6 點 50 分啟動同步處理作業。這個想法比一次性同步處理更為複雜,但我們會推出這項功能。

我們會逐步將 Android 和 iOS 的成功模式引進網頁,同時保留網頁的優點!