日韩一区,国产二区,欧美三区,日本大片在线看黄a∨免费,欧美人体做爰大胆视频,欧洲美女黑人粗性暴交视频,日,韩,欧美一区二区三区

首頁>文檔>科普>什么是Service Worker?Service Worker詳細介紹?

此組別內(nèi)的文章

需要支持?

如果通過文檔沒辦法解決您的問題,請?zhí)峤还潍@取我們的支持!

什么是Service Worker?Service Worker詳細介紹?

Service Worker的由來

W3C 組織早在 2014 年 5 月就提出過 Service Worker 這樣的一個 HTML5 API ,主要用來做持久的離線緩存。service worker是瀏覽器的一個高級特性,本質(zhì)是一個web worker,是獨立于網(wǎng)頁運行的腳本。 web worker這個api被造出來時,就是為了解放主線程。因為,瀏覽器中的JavaScript都是運行在單一個線程上,隨著web業(yè)務(wù)變得越來越復(fù)雜,js中耗時間、耗資源的運算過程則會導(dǎo)致各種程度的性能問題。 而web worker由于獨立于主線程,則可以將一些復(fù)雜的邏輯交由它來去做,完成后再通過postMessage的方法告訴主線程。 service worker則是web worker的升級版本,相較于后者,前者擁有了持久離線緩存的能力。

Service Worker的特點

  • 獨立于主線程、在后臺運行的腳本
  • 被install后就永遠存在,除非被手動卸載
  • 必須是https的協(xié)議才能使用。不過在本地調(diào)試時,在http://localhosthttp://127.0.0.1 下也是可以跑起來的。
  • 不能直接操縱dom:因為sw是個獨立于網(wǎng)頁運行的腳本。
  • 可攔截請求和返回,緩存文件。sw可以通過fetch這個api,來攔截網(wǎng)絡(luò)和處理網(wǎng)絡(luò)請求,再配合cacheStorage來實現(xiàn)web頁面的緩存管理以及與前端postMessage通信。

Service Worker的兼容性

下圖是Service worker現(xiàn)有的瀏覽器支持版本, 從圖上可以看出火狐和谷歌的支持是比較良好的,IE和safari需要相對比較高的版本才能夠支持。移動端的話ios也需要從ios13才開始支持在安卓上的支持會相對廣泛一點。

什么是Service Worker?Service Worker詳細介紹?插圖

Service Worker的工作流程

什么是Service Worker?Service Worker詳細介紹?插圖1
  • Service Worker 文件只在首次注冊的時候執(zhí)行了一次。
  • 安裝、激活流程也只是在首次執(zhí)行 Service Worker 文件的時候進行了一次。
  • 首次注冊成功的 Service Worker 不能攔截當(dāng)前頁面的請求。
  • 非首次注冊的 Service Worker 可以控制當(dāng)前的頁面并能攔截請求
  • Service Worker 首次注冊或者有新版本觸發(fā)更新的時候,才會重新創(chuàng)建一個 worker 工作線程并解析執(zhí)行 Service Worker 文件,在這之后并進入 Service Worker 的安裝和激活生命周期

Service Worker的生命周期

當(dāng)一個servicework被注冊成功后,它將開始它的生命周期,我們對servicework的操作一般都是在其生命周期里面進行的。servicework的生命周期分為這么幾個狀態(tài) 安裝中, 安裝后, 激活中, 激活后, 廢棄。

  • 安裝( installing ):這個狀態(tài)發(fā)生在 Service Worker 注冊之后,表示開始安裝,這個狀態(tài)會觸發(fā) install 事件,一般會在install事件的回調(diào)里面進行靜態(tài)資源的離線緩存, 如果這些靜態(tài)資源緩存失敗了,那 Service Worker 安裝就會失敗,生命周期終止。
  • 安裝后( installed ):當(dāng)成功捕獲緩存到的資源時,servicework會變?yōu)檫@個狀態(tài),當(dāng)此時沒有其他的servicework線程在工作時,會立即進入激活狀態(tài),如果此時有正在工作的servicework工作線程,則會等待其他的 Service Worker 線程被關(guān)閉后才會被激活??梢允褂?self.skipWaiting() 方法強制正在等待的servicework工作線程進入激活狀態(tài)。
  • 激活( activating ):在這個狀態(tài)下會觸發(fā)activate事件,在activate 事件的回調(diào)中去清理舊版緩存。
  • 激活后( activated ):在這個狀態(tài)下,servicework會取得對整個頁面的控制
  • 廢棄狀態(tài) ( redundant ):這個狀態(tài)表示一個 Service Worker 的生命周期結(jié)束。新版本的 Service Worker 替換了舊版本的 Service Worker會出現(xiàn)這個狀態(tài)

更新Service Worker

更新一個servicework,最直接的辦法就是修改servicework.js這個文件,當(dāng)刷新瀏覽器時,瀏覽器嘗試重新下載servicework.js腳本文件,然后會與之前的版本比對,一旦發(fā)現(xiàn)文件內(nèi)容不一致,就會進入更新流程。

  • 新的 servicework 被啟動安裝并觸發(fā) install事件。
  • 安裝成功后,新版 servicework 進入等待狀態(tài),此時頁面的控制權(quán)還在老版 servicework手中。
  • 當(dāng)servicework控制的所有終端都關(guān)閉之后,或者手動self.skipWaiting(),舊的 servicework 才能被終止,此時新的servicework被激活,觸發(fā)activate 事件。
  • 用戶再次訪問頁面,或刷新頁面,新的 service work 啟動控制頁面。

Service Worker 的簡單實踐

  1. 注冊。 serviceWorker對象存在于navigator對象下,可以再主線程中調(diào)用navigator.serviceWorker.register()方法來注冊servicework,register 方法接受兩個參數(shù),第一個參數(shù)表示servicework.js相對于origin的路徑,第二個參數(shù)是 Serivce Worker 的配置項,可選填,其中比較重要的是 scope 屬性,用來指定你想讓 service worker 控制的內(nèi)容的目錄。 默認值為servicework.js所在的目錄。這個屬性所表示的路徑不能在 service worker 文件的路徑之上,默認是 Serivce Worker 文件所在的目錄。 成功注冊或返回一個promise。

// 頁面的入口文件

if (navigator.serviceWorker) {
  window.addEventListener('load', () => {
    console.log('開始注冊ServiceWorker')
    navigator.serviceWorker
      .register('./serviceworker.js')
      .then((reg) => {
        console.log('ServiceWorker register success: ', reg)
      })
      .catch((err) => {
        console.log('ServiceWorker register failed: ', err)
      })
  })
}

  1. 安裝

self.addEventListener('install', (event) => {
  console.log('install事件')
  self.skipWaiting() //用來強制更新的servicework跳過等待時間
  event.waitUntil(
    caches.open(CACHE_NAME).then(function (cache) {
      return cache.addAll(urlsToCache)
    })
  )
})

首先 self.skipWaiting() 執(zhí)行,告知瀏覽器直接跳過等待階段,淘汰過期的Service Worker腳本,直接開始嘗試激活新的Service Worker。然后使用 caches.open 打開一個Cache,打開后,通過cache.addAll嘗試緩存我們預(yù)先聲明的文件。 CacheStorage 全局的cache Api 并非只有在sw中才能用 瀏覽器控制臺直接用也是可以的,所以是掛在window下的

event.waitUntil() 只能在 Service Worker 的 install 或者 activate 事件中使用;看起來像是一個 callback,用來延長事件的作用時間,但是,即便你不使用它,程序也可能正常運行。如果你傳遞了一個 Promise 給它,那么只有當(dāng)該 Promise resolved 時,Service Worker 才會完成 install;如果 Promise rejected 掉,那么整個 Service Worker 便會被廢棄掉。因此,cache.addAll 里面,只要有一個資源獲取失敗,整個 Service Worker 便會失效。

在 install 事件回調(diào)被調(diào)用時,它把即將被激活的 worker 線程狀態(tài)延遲為 installing 狀態(tài),直到傳遞的 Promise 被成功地 resolve。這主要用于確保:Service Worker 工作線程在所有依賴的核心 cache 被緩存之前都不會被激活。

在 activate 事件回調(diào)被調(diào)用時,它把即將被激活的 worker 線程狀態(tài)延遲為 activating 狀態(tài),直到傳遞的 Promise 被成功地 resolve。這主要用于確保:任何功能事件不會被分派到 ServiceWorkerGlobalScope 對象,直到它刪除過期的緩存條目。

當(dāng) waitUntil()運行時,如果 Promise 是 rejected 那么installing 或者 activating 的狀態(tài)會被設(shè)置為 redundant。

  1. 激活

self.addEventListener('activate', (event) => {
  console.log('activate事件')
  var cacheWhitelist = [CACHE_NAME]
  self.clients.claim() // 保證 激活之后能夠馬上作用于所有的終端
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames.map((cacheName) => {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName)
          }
        })
      )
    })
  )
})

在激活servicework時需要刪除之前的緩存,可將需要的緩存放在有個白名單中,然后通過caches.keys()拿到所有緩存,將不再白名單中的緩存刪掉。

  1. 攔截網(wǎng)絡(luò)請求

  self.addEventListener('fetch', (event) => {
    event.respondWith(
      caches.match(event.request).then((response) => {
        if (response) 
          return response;
        }
        return fetch(event.request);
      })
    );
  });

通過監(jiān)聽servicework的 fetch 事件來攔截網(wǎng)絡(luò)請求,調(diào)用 event 上的 respondWith() 方法來劫持當(dāng)前servicework控制域下的 HTTP 請求,該方法會直接返回一個Promise 結(jié)果 ,這個結(jié)果就會是http請求的響應(yīng)。上面代碼中就一個簡單的邏輯,先劫持http請求,然后看看緩存中是否有這個請求的資源,如果有則直接返回,如果沒有就去請求服務(wù)器上的資源。 event.respondWith 方法只能在 Service Worker 的 fetch 事件中使用。

Cache Stroage 只能緩存靜態(tài)資源,所以它只能緩存用戶的 GET 請求;Cache Stroage 中的緩存不會過期,但是瀏覽器對它的大小是有限制的,所以需要我們定期進行清理。
對應(yīng)post 請求我們也可以通過 fetch方法攔截到,來進行一些自定義的返回。

  1. service worker 與主線程之間的通信
  • 主線程

  // 傳遞
  navigator.serviceWorker.controller && navigator.serviceWorker.controller.postMessage("this message is from page");

  // 接收
  navigator.serviceWorker.addEventListener('message', function (e) {
    console.log('service worker傳遞的信息',e.data); 
  });
  • service worker

self.addEventListener('message', (event)=>{
  console.log('頁面?zhèn)鬟f過來的數(shù)據(jù)',event.data)  // 收到主線程傳遞的信息
  event.source.postMessage('this message is from sw.js to page');  // 向主線程傳遞信息
})

  1. service worker 卸載

  navigator.serviceWorker.getRegistrations().then(function (registrations) {
    for (let registration of registrations) {
      //安裝在網(wǎng)頁的service worker不止一個,找到我們的那個并刪除
      console.log(registration)
      if (registration && registration.scope === 'http://localhost:8080/') {
        registration.unregister()
      }
    }
  })
  1. serviceworker 和 http緩存
  • 在請求速度方面:
什么是Service Worker?Service Worker詳細介紹?插圖2
  • 在緩存文件更新方面
    • 如果是http緩存,一刷新頁面就可以拿到最新的資源
    • 如果是sw緩存, 一刷新頁面,會返回當(dāng)前緩存中的資源(不是最新),然后請求sw.js文件發(fā)現(xiàn)更新后重新進入sw生命周期,重新去更新緩存,當(dāng)你再次刷新時才能拿到最新資源。所以在緩存資源更新時,sw會延遲一次刷新才能獲取最新資源
  • 在緩存控制方面: http一般是由服務(wù)器端控制的,而sw則是可以前端自己控制,可以更好地控制緩存。 協(xié)商緩存返回狀態(tài)碼304, 強緩存返回的是200, 在這點上server worker和強緩存比較類似的返回也是200, 會對請求進行攔截,不會真是的發(fā)出請求。

其他

會有一些開源的框架對 service worker進行了一些封裝,避免了我們重復(fù)繁瑣的去寫一下fetch監(jiān)聽,install事件,active事件等,大大簡化了繁瑣的寫法。關(guān)注度比較高的應(yīng)該是谷歌推出的 workbox, 圍繞他也有一系列的工具,如 workbox-cli、gulp-workbox、webpack-workbox-plagin 等等。

workbox提供了一下幾種緩存策略:

  • Stale-While-Revalidate 當(dāng)請求的路由有對應(yīng)的 Cache 緩存結(jié)果就直接返回,在返回 Cache 緩存結(jié)果的同時會在后臺發(fā)起網(wǎng)絡(luò)請求拿到請求結(jié)果并更新 Cache 緩存,如果本來就沒有 Cache 緩存的話,直接就發(fā)起網(wǎng)絡(luò)請求并返回結(jié)果 ( 從緩存中讀取資源的同時發(fā)送網(wǎng)絡(luò)請求更新本地緩存 )
  • CacheFirst 當(dāng)匹配到請求之后直接從 Cache 緩存中取得結(jié)果,如果 Cache 緩存中沒有結(jié)果,那就會發(fā)起網(wǎng)絡(luò)請求,拿到網(wǎng)絡(luò)請求結(jié)果并將結(jié)果更新至 Cache 緩存,并將結(jié)果返回給客戶端。這種策略比較適合結(jié)果不怎么變動且對實時性要求不高的請求。 (有緩存用緩存,無緩存則請求網(wǎng)絡(luò))
  • CacheOnly 這個策略也比較直接,直接使用 Cache 緩存的結(jié)果,并將結(jié)果返回給客戶端,這種策略比較適合一上線就不會變的靜態(tài)資源請求。 (僅使用緩存)
  • NetworkFirst 采用網(wǎng)絡(luò)優(yōu)先的策略,也就是優(yōu)先嘗試拿到網(wǎng)絡(luò)請求的返回結(jié)果,如果拿到網(wǎng)絡(luò)請求的結(jié)果,就將結(jié)果返回給客戶端并且寫入 Cache 緩存,如果網(wǎng)絡(luò)請求失敗,那最后被緩存的 Cache 緩存結(jié)果就會被返回到客戶端,這種策略一般適用于返回結(jié)果不太固定或?qū)崟r性有要求的請求,為網(wǎng)絡(luò)請求失敗進行兜底。 (有網(wǎng)的情況下采取網(wǎng)絡(luò),沒網(wǎng)的情況下用緩存)
  • NetworkOnly 比較直接的策略,直接強制使用正常的網(wǎng)絡(luò)請求,并將結(jié)果返回給客戶端,這種策略比較適合對實時性要求非常高的請求。 (僅使用網(wǎng)絡(luò)請求)

0 條回復(fù) A文章作者 M管理員
    暫無討論,說說你的看法吧
QQ客服
  • QQ176363189 點擊這里給我發(fā)消息
旺旺客服
  • 速度網(wǎng)絡(luò)服務(wù)商 點這里給我發(fā)消息
電子郵箱
  • sudu@yunjiasu.cc
微信客服
  • suduwangluo