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