初識 ServiceWorker

初識ServiceWorker

初識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
確保以上兩個步驟都完成後,就可以在控制檯看到返回值:
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簡單例子

Github上一些代碼

W3C ServiceWorkers

文章作者:foreverpx
文章原文鏈接:初識ServiceWorker

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章