Service Worker

Service Worker是什么


從功能上來說奕污,Service Worker是一種提供離線緩存控制功能的一種Worker千诬,同時,也具有消息推送和后臺同步的功能抗楔,可以通過Service Worker來緩存網(wǎng)頁的資源俊扭,然后攔截Fetch請求來執(zhí)行相應的緩存處理操作队橙。因為是一種Worker,所以Service Worker也具有Worker的一些基本特性萨惑,例如:

  • 獨立于主線程運行
  • 不能訪問window對象捐康,但是擁有自身的一個執(zhí)行上下文,例如Service WorkerServiceWorkerGlobalScope
  • 具有消息api來和頁面進行消息交互

Service Worker是一種共享型Worker庸蔼,它不同于專用型Worker只能在創(chuàng)建它的頁面中使用解总,默認配置下,service Worker可以被當前注冊腳本的域名下所有頁面公用姐仅。
也就是說倾鲫,只要在一個根域名注冊一個ServiceWorker,那么所有這個域名下的頁面都會收到影響萍嬉。

Service Worker使用


要使用ServiceWorker乌昔,首先,需要通過serviceWorkerContainer.register()來進行注冊壤追,例如:

ServiceWorkerContainer.register("/test/service.js", {scope:"./"})
    .then(
        function(ServiceWorkerRegistration) {
            // do something
        }
);

假設當前域名為www.baidu.com/serviceWork磕道,那么上面的方法就在www.baidu.com/serviceWork/test下面注冊了一個ServiceWorker,假如把scope改成./hahaha行冰,那么作用域就變成了www.baidu.com/serviceWork/test/hahaha溺蕉,只要處于這個域名之下的所有頁面,都受到這個ServiceWorker的控制悼做。但是疯特,假如將scope改成"../",頁面就會報出一個錯誤肛走,因為這時候不允許設置比service.js所在位置層級更高的路徑漓雅,除非添加一個Service-Worker-Allowedheader。

注冊完成之后,受控界面會去安裝serviceWorker邻吞,安裝完成之后會處于等待狀態(tài)组题,接下來有可能會進入激活狀態(tài),激活狀態(tài)之后抱冷,頁面還不一定是受控的崔列,不過有相應的api可以控制這一系列流程。這些流程就是ServiceWorker最最復雜的生命周期了旺遮。

ServiceWorker生命周期


serviceWorker的生命周期有點復雜赵讯,情況很多,但是基本上符合一個理念耿眉,那就是漸進式边翼。

install

執(zhí)行完注冊之后,瀏覽器會去下載跷敬,假如腳本沒有錯誤的話讯私,就會進行安裝热押,安裝會在Worker內(nèi)觸發(fā)install事件西傀,安裝分為兩個狀態(tài):installinginstalled,這里可以執(zhí)行一些操作桶癣。

self.addEventListener("install",installEvent=>{
    self.skipWaiting();//跳過waiting
    installEvent.waitUntil(
        caches.open(CACHE_NAME).then(cache=>{
            return cache.add("http://upload.jianshu.io/users/upload_avatars/9545112/f186bd4a-1da4-4912-b926-a744bc128d06.png?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240");
        })
    )

});

這里會有一個installEvent拥褂,通過waitUtil方法可以阻塞安裝狀態(tài),這個方法可以傳入一個promise牙寞,只有這個promise正確resolve之后饺鹃,才會完成安裝,同時间雀,還有一個skipwaiting方法悔详,這個方法可以跳過installed和activating狀態(tài)之間的waiting狀態(tài)。
首次打開頁面會安裝work惹挟,然后接下來再檢測到新的work也會再次執(zhí)行安裝茄螃。
觸發(fā)更新的幾種情況:

  • 第一次導航到作用域范圍內(nèi)頁面的時候
  • 當在24小時內(nèi)沒有進行更新檢測并且觸發(fā)功能性時間如push或sync的時候
  • SW 的 URL 發(fā)生變化并調(diào)用.register()時
  • 手動執(zhí)行reg.update()
  • 重載頁面(有些情況下不會更新,原因不明)

更新會比對舊版本和新版本的字節(jié)连锯,假如字節(jié)不一致归苍,則更新。在更新install完成之后运怖,會進入waiting狀態(tài)拼弃,直到舊版本不控制任何client(受控的頁面)再進入activating狀態(tài)。

activate

activate的狀態(tài)比測試妹子的思考邏輯還難猜測摇展。但是這個遵循一個原則吻氧,只有所有的頁面都不受老的serviceWorker控制的時候,才會開始激活。意思就是所有worker作用的頁面都關(guān)了医男,相當于重啟更新砸狞,再次啟動的時候,才會進入激活狀態(tài)镀梭。激活也會觸發(fā)一個activate狀態(tài).

self.addEventListener("activate", ExtendableEvent => {
  ExtendableEvent.waitUntil(self.clients.claim());
 }

activate也和install一樣刀森,也有waitUtil方法,效果也是一樣的报账。激活完成之后其實還不一定有效果研底,因為頁面可能還處于不受控的狀態(tài),或者有另外一個頁面透罢,沒有刷新的榜晦,但是這個時候新開一個頁面更新了work,這個時候就需要調(diào)用clients.claim操作來讓所有打開的頁面受控羽圃。但是...work的執(zhí)行是異步的乾胶,也就是說,頁面在執(zhí)行這個方法之前是不受控朽寞,或者是不是受最新的work控制的识窿,在利用work來緩存的時候,就會出現(xiàn)問題脑融,導致版本不一致喻频,所以,個人感覺serviceWorker比較適合做一個輔助者肘迎,沒有也行甥温,有也行,可以通過設置一個button之類的來提醒用戶妓布,發(fā)現(xiàn)新版本姻蚓,是否需要刷新之類的操作。
下面這張圖很好的概括了生命周期

生命周期

Fetch

激活完成之后匣沼,work內(nèi)可以攔截到fetch事件狰挡,通過這個,就可以執(zhí)行緩存操作肛著。fetch事件回調(diào)會返回一個fetchEvent對象圆兵,通過fetchEvent.respondWith()可以自定義返回的response。

其他事件

....

雜談


ServiceWorker的大多數(shù)功能都要在worker線程中使用枢贿,在頁面中殉农,通過注冊返回的ServiceWorkerRegistration可以獲取很多有用的信息,例如正在安裝的worker局荚,等待中的worker超凳,激活的worker愈污,worker作用域等。同時轮傍,可以監(jiān)聽狀態(tài)的變換暂雹。例如,

ServiceWorkerRegistration.addEventListener("updatefound",()=>{
            const netWorker=ServiceWorkerRegistration.installing;
            console.log(`state:${netWorker.state}`);
            netWorker.addEventListener("statechange", () => {
              // newWorker 狀態(tài)發(fā)生變化
              console.log(`state變換:${netWorker.state}`)
              if(netWorker.state=="installed"){
                console.log("檢測到新版本!");
              }
            });
        })

這里创夜,先獲取正在安裝中的worker杭跪,然后監(jiān)聽狀態(tài)變換,當切換成installed狀態(tài)時驰吓,假如之前已經(jīng)存在serviceWorker涧尿,就可以判定新安裝的worker是更新進去的,這個時候就有可能部分資源是通過老的worker緩存請求的檬贰,部分資源在worker受控之后是通過worker緩存請求的姑廉,這樣就存在不一致的問題,所以這時候就可以提醒用戶有新版本更新翁涤,從而刷新更新桥言。假如之前沒有worker,那么就說明這個worker是第一次注冊安裝葵礼,因為是第一次号阿,所以沒有所謂的緩存資源版本不一致的問題,沒必要提醒用戶更新章咧。
針對serviceWorker機制所導致的各種資源同步問題倦西,將其想像成漸進式的就輕松多了能真,將worker當作一個輔助者赁严,把緩存想象成可有可無的。進一步來看可以不使用skipWaiting粉铐,只有在用戶重啟的時候才可以更新疼约,這時候所有的資源就不存在不同步的問題了,所有的請求都會在重啟更新之后直接進入worker蝙泼。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末程剥,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子汤踏,更是在濱河造成了極大的恐慌织鲸,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溪胶,死亡現(xiàn)場離奇詭異搂擦,居然都是意外死亡,警方通過查閱死者的電腦和手機哗脖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門瀑踢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扳还,“玉大人,你說我怎么就攤上這事橱夭“本啵” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵棘劣,是天一觀的道長俏让。 經(jīng)常有香客問我,道長茬暇,這世上最難降的妖魔是什么舆驶? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮而钞,結(jié)果婚禮上沙廉,老公的妹妹穿的比我還像新娘。我一直安慰自己臼节,他們只是感情好撬陵,可當我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著网缝,像睡著了一般巨税。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粉臊,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天草添,我揣著相機與錄音,去河邊找鬼扼仲。 笑死远寸,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的屠凶。 我是一名探鬼主播驰后,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼矗愧!你這毒婦竟也來了灶芝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤唉韭,失蹤者是張志新(化名)和其女友劉穎夜涕,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體属愤,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡女器,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年晓避,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暑塑。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡事格,死狀恐怖搞隐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逢捺,我是刑警寧澤癞季,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布绷柒,位于F島的核電站废睦,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏奈应。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一钥组、第九天 我趴在偏房一處隱蔽的房頂上張望今瀑。 院中可真熱鬧点把,春花似錦、人聲如沸郎逃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朵你。三九已至,卻和暖如春躲因,著一層夾襖步出監(jiān)牢的瞬間忌傻,已是汗流浹背水孩。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工俘种, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抛杨。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓怖现,卻偏偏與公主長得像玉罐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子饶号,可洞房花燭夜當晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容