摘要:再次修改控制臺輸出也就是說激活過程中的任何錯誤不影響被激活腦洞下新激活過程中說明頁面已經沒有被其他控制了,所以事件回調函數的執行失敗并不會影響被激活。
ServiceWorker生命周期
ServiceWorker本身是有狀態的(installing,installed,activating,activated,redundant),這些狀態構成了ServiceWorker生命周期:
生命周期可細分為兩個過程:
安裝過程(installing,installed)
激活過程(activating, activated)
1. installing當使用方法navigator.serviceWorker.register注冊一個新的ServiceWorker時,瀏覽器會下載JS腳本,解析腳本。這時ServiceWorker處于installing狀態。如果安裝成功,則進入installed狀態,否則會進入redundant狀態。
1.1 InstallEvent對象處于installing時會觸發ServiceWorkerGlobalScope上下文的install事件。
index.html:
Service Life Cycle
sw.js 文件內容:
self.addEventListener("install", function(event) { console.log("install callback") })
可通過registration.installing屬性訪問處于install狀態的ServiceWorker;
在ServiceWorkerGlobalScope中可以綁定多個install事件回調函數,多個事件回調函數的參數是同一個InstallEvent對象;
如果install事件回調函數拋異常,則視為安裝失敗,ServiceWorker會進入redundant狀態;
如果回調函數里調用installEvent.waitUntil(promise1)方法,則promise1被resolved時ServiceWorker對象才被installed,如果promise1被rejected則SW安裝失敗(redundant);
同一個事件回調函數或者多個事件回調函數可以多次調用installEvent.waitUntil(promise)方法,則表達所有的promise都被resolved時SW對象才被installed,只要存在promise被rejected則SW安裝失敗(redundant)。
修改sw.js內容,重新注冊sw:
self.addEventListener("install", function(event) { event._from = "callback1" console.log("install callback 1: " + (Date.now()/1000)) var i = 0; while(i < 1000000) { ++i; } // 多次調用 event.waitUntil(new Promise(function(resolve) { setTimeout(() => { console.log("resolve 2s") resolve() }, 2000) })) event.waitUntil(new Promise(function(resolve, reject) { setTimeout(() => { console.log("resolve 3s") resolve() // }, 3000) })) }) // 多次綁定Install事件 self.addEventListener("install", function(event) { event._from = "callback2" console.log("install callback 2: " + (Date.now()/1000)) event.waitUntil(new Promise(function(resolve) { setTimeout(() => { console.log("resolve 5s") resolve() }, 5000) })) })
觀察控制臺輸出
1.2 waitUntil方法InstallEvent對象從父對象ExtendableEvent繼承了waitUntil方法。該方法延長了事件對象的生存期。當傳給waitUntil方法的Promise對象轉成終態(resolved/rejected)才認為事件對象被處理完了。在事件對象被處理完之前ServiceWorker不會進入下一個狀態(installed或者redundant)。
2. installed/waitingServiceWorker成功安裝后便進入installed狀態。至此Service完成了安裝過程,等待進入激活過程。
可通過registration.waiting屬性訪問處于installed狀態的ServiceWorker(見上例);
如果頁面沒有激活的ServiceWorker管理,則ServiceWorker進入activating狀態。
3. activatingServiceWoker安裝成功后進入activating狀態。
3.1 ActivateEvent對象處于activating時會觸發ServiceWorkerGlobalScope上下文的activate事件。
可以綁定多個事件回調函數,多個事件回調ActivateEvent對象是同一個對象;
如果回調函數里調用activateEvent.waitUntil(promise1)方法,則表示promise1被resolved/rejected時SW對象才進入下一個狀態activated;
同一個事件回調函數或者多個事件回調函數可以多次調用activateEvent.waitUntil(promise)方法,則表達所有的promise都被resolved/rejected時SW對象才進入下一個狀態activated;
修改sw.js文件:
self.addEventListener("activate", function(event) { event._from = "callback1" console.log("activate callback 1: " + (Date.now()/1000)) var i = 0; while(i < 1000000) { ++i; } event.waitUntil(new Promise(function(resolve, reject) { setTimeout(() => { console.log("resolve 2s") resolve() }, 2000) })) event.waitUntil(new Promise(function(resolve, reject) { setTimeout(() => { console.log("resolve 4s") resolve() }, 4000) })) }) self.addEventListener("activate", (event) => { event.waitUntil(new Promise((resolve, reject) =>{ setTimeout(() => { resolve("resolve activate") }, 5000) })) })
控制臺輸出:
跟install事件回調函數不一樣的是在activate事件回調函數里拋異常,或者傳給activateEvent.waitUntil(promise1)方法的promise被reject都不會影響ServiceWorker進入activated狀態。
再次修改sw.js:
self.addEventListener("activate", function(event) { event._from = "callback1" console.log("activate callback 1: " + (Date.now()/1000)) var i = 0; while(i < 1000000) { ++i; } event.waitUntil(new Promise(function(resolve, reject) { setTimeout(() => { console.log("resolve 2s") resolve() }, 2000) })) event.waitUntil(new Promise(function(resolve, reject) { setTimeout(() => { console.log("resolve 4s") resolve() }, 4000) })) }) self.addEventListener("activate", (event) => { throw "error" event.waitUntil(new Promise((resolve, reject) =>{ setTimeout(() => { resolve("reject activate") }, 1) })) }) self.addEventListener("activate", (event) => { event.waitUntil(new Promise((resolve, reject) =>{ setTimeout(() => { reject("reject activate") }, 5000) })) })
控制臺輸出:
也就是說激活過程中的任何錯誤不影響ServiceWoker被激活(腦洞下:新SW激活過程中說明頁面已經沒有被其他SW控制了,所以activate事件回調函數的執行失敗并不會影響SW被激活。),注意這一點跟其他文檔描述的可能不太一樣。
4. activated這時ServiceWorker可以控制頁面了,可以監聽功能事件了,如fetch,push事件。默認情況下ServiceWorker只能控制在其激活成功后才加載完成的頁面。
4.1 fetch事件 & FetchEvent對象ServiceWorker控制頁面后就可以監聽fetch事件了: 捕獲請求,構建響應。注意:保證一個請求只有一個響應
可以綁定多個fetch事件,并且多個回調函數的fetchEvent是同一個對象;
如果回調函數內成功調用了fetchEvent.respondWith方法,則后面的回調函數不會被執行;
回調函數里多次調用fetchEvent.respondWith會報錯的,即一個request只能有一個reponse;
回調函數里最好是同步的方式調用fetchEvent.respondWith,異步調用不會阻止后面的后調函數執行, 很容易會造成多個reponse,導致錯誤3;
如果所有的回調函數里都沒有調用fetchEvent.respondWith方法則會采用瀏覽器默認的fetch事件回調函數處理方式,即走網絡請求;
fetch回調函數還可以調用waitUntil方法,來延長FetchEvent事件對象的生命,如果有FetchEent對象還未處理完瀏覽器是不會自動關閉SW的。
5. redundantredundant狀態是ServiceWorker的終態。 關于serviceWorker如何變成redundant狀態在Lavas Service Worker 生命周期和 the-service-worker-lifecycle參考中列舉了3種,但是測試發現激活失敗并不會導致哎,見上例。在這本書里Building Progressive Web Apps by Tal Ater的觀點貌似論證了我們代碼。這里再匯總下進入redundant的case:
register失敗,如多次調用register,后調用注冊的SW會變成redundant
安裝失敗
被新版本的ServiceWorker替換
再強調下激活過程不會導致ServiceWorker變成redundant狀態。
參考Google 服務工作線程生命周期
Chapter 4. Service Worker Lifecycle and Cache Management
The Service Worker Lifecycle
Lavas Service Worker 生命周期
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99296.html
前提 本文涉及幾個知識點:fetch、caches、indexDB 等都不會詳細介紹,僅對于其中某些點帶過 一. 概念 serviceWorker,服務工作線程,顧名思義,只是作為工作線程存在,不摻和到JS主線程中來,介于 瀏覽器 & 服務器中間層,可攔截指定 client 所發起的所有請求 二. 用途 目前 PWA(Progress Web App) 的概念很火,大致就是讓 web 也跟 app...
摘要:配合的項,能夠實現緩存外部資源的功能。允許接受來自的消息,默認值為。檢查新版本的的更新信息。這也是我在研究階段直接使用時所發現的問題。建議僅在生產模式內使用。 showImg(https://segmentfault.com/img/bVSVG1?w=1178&h=484); 談起PWA,許多人可能還只停留在了解的層面,比較少在實踐中真正地嘗試過,更多的僅僅是對著網上的教程和例子大概玩...
摘要:技術實現離線應用的核心是離線緩存技術,歷史上曾先后出現兩種離線緩存技術。新的線程取得控制權后,將會觸發其事件。接入用構建接入的離線應用時,要解決的問題在于如何生成之前提到的文件。 內容主要引用自吳浩麟著《webpack深入淺出》 離線應用 離線應用的優點: 在沒有網絡的情況下能打開網頁。 由于部分緩存的資源直接從本地加載,所以對用戶來說可以加快網頁的加載速度,減少服務器壓力。 技術實...
摘要:我喜歡移動,而且也是那些堅持使用技術構建移動應用程序的人之一。我們準備做這樣的一個漸進式應用是典型的旨在提高用戶離線體驗的應用。當我們開始構建應用時,你就能理解上面的場景了。的作用范圍是針對相對路徑的。最佳的做法是在應用的入口。 我喜歡移動app,而且也是那些堅持使用Web技術構建移動應用程序的人之一。 經過技術的不斷迭代(可能還有一些其它的東西),移動體驗設計愈來愈平易近人,給予用戶...
閱讀 1599·2021-11-22 09:34
閱讀 1690·2019-08-29 16:36
閱讀 2668·2019-08-29 15:43
閱讀 3113·2019-08-29 13:57
閱讀 1297·2019-08-28 18:05
閱讀 1874·2019-08-26 18:26
閱讀 3242·2019-08-26 10:39
閱讀 3454·2019-08-23 18:40