初識ServiceWorker
在8月份的時候,W3C更新了一個叫Service Workers的API。
瞭解過HTML5中的Web Worker的人可能會對這個API會更容易理解一些,不然的話會將這兩個API搞混。
其實,Service Worker是基於Web Worker的事件驅動的,他們執行的機制都是新開一個線程去處理一些額外的,以前不能直接處理的任務。對於Web Worker,我們可以使用它來進行復雜的計算,因爲它並不阻塞瀏覽器主線程的渲染。而Service Worker,我們可以用它來進行本地緩存,相當於一個本地的proxy。說起緩存,我們會想起我們常用的一些緩存技術來緩存我們的靜態資源,但是老的方式是不支持調試的,靈活性不高。使用Service Worker來進行緩存,我們可以用javascript代碼來攔截瀏覽器的http請求,並設置緩存的文件,直接返回,不經過web服務器,然後,做更多你想做的事情。
因此,我們可以開發基於瀏覽器的離線應用。這使得我們的web應用減少對網絡的依賴。例如,我們開發了一個新聞閱讀的web應用,當你用手機瀏覽器在有網絡的情況下打開時,你可以正常的獲取新聞內容。可是,如果手機進入飛行模式,那這個應用你就沒法使用了。
如果我們使用了Service Worker做緩存,瀏覽器http請求會先經過Service Worker,通過url mapping去匹配,如果匹配到了,則使用緩存數據,如果匹配失敗,則繼續執行你指定的動作。一般情況下,匹配失敗則讓頁面顯示“網頁無法打開”。
上面是Service Worker的基本使用場景,當然,不僅僅侷限於數據緩存。
下面來看一個簡單的示例:
/index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <script> // scope defaults to "/*" navigator.serviceWorker.register("/service-worker.js").then(function(serviceWorker) { console.log("success!"); // To use the serviceWorker immediately, // you might call window.location.reload() }); </script> </head> <body> </body> </html>
|
在chrome中的console中輸入navigator.serviceWorker你會發現返回的undefined。這可能是因爲你chrome的版本小於36,或者你沒有打開這個功能。所以先確保你的chrome升級到了36以上。然後進入chrome://flags/中將ServiceWorker開關打開,如下圖:
確保以上兩個步驟都完成後,就可以在控制檯看到返回值:
上面的代碼中,給serviceWorker註冊了一個叫service-worker.js的文件,這裏採用的promise寫法。當註冊成功後,會執行then裏面的回調函數。
下面看看service-worker.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
this.oninstall = function(e) { // Create a cache of resources. var resources = new Cache(); var visited = new Cache(); // Fetch them. e.waitUntil(resources.add( "/index.html", "/fallback.html", "/css/base.css", "/js/app.js", "/img/logo.png" ).then(function() { // Add caches to the global caches. return Promise.all([ caches.set("v1", resources), caches.set("visited", visited) ]); })); }; this.onfetch = function(e) { e.respondWith( // Check to see if request is found in cache caches.match(e.request).catch(function() { // It's not? Prime the cache and return the response. return caches.get("visited").then(function(visited) { return fetch(e.request).then(function(response) { visited.put(e.request, response); // Don't bother waiting, respond already. return response; }); }); }).catch(function() { // Connection is down? Simply fallback to a pre-cached page. return caches.match("/fallback.html"); }); ); };
|
oninstall:當worker裝載完畢時執行
在oninstall的回調函數中,將一些需要緩存的靜態的文件寫入全局的cache對象中。
onfetch:當接收到用戶的請求時執行
通過e.request去匹配緩存中的靜態文件,如果匹配到,則將這個緩存文件返回,如果未匹配到,則被catch獲取,將請求釋放(去請求真正的服務器),並將這個新文件緩存到全局cache。這裏也是用到了promise寫法。
在我看來,用ServiceWorker做緩存就相當於一個proxy,可以攔截http請求,這樣你可以對請求做一下定製化的需求。即使在無網絡的情況下,ServiceWorker也可以被當做一個http服務器一樣返回前端所需要的數據。
上面是我對ServiceWorker的一些參考和理解。目前相關的中英文資料還比較少,主要還是得看W3C的介紹。
參考資料:
ServiceWorker簡單例子
文章作者:foreverpx
文章原文鏈接:初識ServiceWorker