http://www.w3.org/TR/2014/WD-service-workers-20140508/#introduction 下面將從webWorker、serviceWorker和爲何使用serviceWorker三個方面進行討論javascript
要了解serviceworker,先的認識下webworker,也能夠了解一下兩者的共同點,並予以區分。html
Web Workers 是 現代瀏覽器 提供的一個javascript多線程解決方案,咱們能夠將一些大計算量的代碼交由web Worker運行。JavaScript語言執行採用的是單線程模型,也就是說,全部任務排成一個隊列,一次只能作一件事。可是有了webworker後就不同了。html5
支持的瀏覽器包括IE十、Firefox (從3.6版本開始)、Safari (從4.0版本開始)、Chrome 和 Opera 11+,可是手機瀏覽器還不支持。java
構造一個webworker:new Worker(path) ,返回一個Worker對象。git
返回的對象github
onerror:用於worker出錯處理 onmessage:用戶主線程和worker線程傳遞數據,可使字符串數字或對象,可是safari瀏覽器不支持對象,須要用stringify和parse轉化。固然和可使用addeventListener("message",function(){}); 煮個栗子:(例子代碼見附件)web
輸出sql
如何結束worker: 主頁面worker.terminate();或worker自銷燬self.close();或者關閉頁面chrome
sharedworker: 除了webWorker,還有另外一類sharedworker支持多個瀏覽器窗口共享同一個worker,單個頁面關閉,worker並不結束,需關閉瀏覽器。但這裏不作深刻討論json
importScripts: worker內部引用文件的方法,能夠將worker分紅不一樣的多個文件,而後使用importScripts加載,並能夠實現文件的動態加載。就像html中使用script標籤引入js同樣。 global worker上下文: 前面提到在worker中不能使用window對象和docuemnt對象,是由於一個webworker擁有一個獨立的運行環境Workerglobalscope並和瀏覽器的環境獨立,Workerglobalscope環境包括:
(3) 侷限性
1.同源限制。webworker不能跨域加載JS 2.DOM限制。worker內代碼不能訪問dom,緣由是worker有本身獨立的global worker環境,不是瀏覽器window,因此alert(),dom等操做沒法進行 3.文件限制。子線程沒法讀取本地文件,即worker只能加載網絡文件。 4.不是每一個瀏覽器都支持這個新特性,且各個瀏覽器對Worker的實現不大一致,例如FF裏容許worker中建立新的worker,而Chrome中就不行
Service Worker是基於Web Worker的事件驅動的,他們執行的機制都是新開一個線程去處理一些額外的,之前不能直接處理的任務。對於Web Worker,咱們可使用它來進行復雜的計算,由於它並不阻塞瀏覽器主線程的渲染。而Service Worker,咱們能夠用它來進行本地緩存或請求轉發,至關於一個瀏覽器端本地的proxy。
例如使用Service Worker來進行緩存,是用javascript代碼來攔截瀏覽器的http請求,並設置緩存的文件,直接返回,不通過web服務器,而後,咱們就能夠開發基於瀏覽器的離線應用。這使得咱們的web應用減小對網絡的依賴。 若是咱們使用了Service Worker作緩存,瀏覽器http請求會先通過Service Worker,經過url mapping去匹配,若是匹配到了,則使用緩存數據,若是匹配失敗,則繼續執行你指定的動做。通常狀況下,匹配失敗則讓頁面顯示「網頁沒法打開」。
上面是Service Worker的一個基本使用場景,固然還有更多,先了解一下serviceWorker。
https://jakearchibald.github.io/isserviceworkerready/ (目前API支持現狀,有興趣的本身看,反正就是基本上只有chrome測試版和FF nightly版本支持)
chrome版本下要支持還要開啓serviceWorker支持,打開chrome://flags/
此外特定的API還須要特定的環境:
此外還有開啓實驗平臺、使用chrome canary測試版本,這個確實比較麻煩。可是實際上使用最新的canary版本也沒法徹底支持草案中的全部API,實驗時使用的chrome穩定37版本和canary 40版本環境。可能後面新版本又會修改。
ServiceWorkerGlobalScope部分做用域定義以下
能夠看出,這個webworker的scope有點不同,可是也有些共同部分 scriptCache:worker的文件一旦註冊使用,會被緩存到瀏覽器中,須要手動清理掉,例如: ,註冊使用了sw.js,sw.js修改後必須清理緩存後才生效
client:返回serviceworkClients對象 scope:返回serviceworker的url路徑數組,並和serviceworker的註冊事件關聯,一旦註冊,serviceworker的路徑就會在scope中。 註冊與銷燬:register&unregister,register執行後返回一個Promise對象,因此要支持serviceWorker瀏覽器必須先支持Promise 事件Event: *install:worker使用register註冊時會觸發install事件 *activate:worker使用register註冊時也會觸發activate事件 *fetch:瀏覽器發送請求時會產生fetch事件,此時能夠調用一個請求響應的對象,或者可使用responseWith來指定請求返回內容 *responseWith:responseWith必須指定一個相應內容,不然會發生觸發error event,請求成功後會得到一個正確的url。 *waitUtil:waitUtil能夠爲install指定時間延時,讓install的動做延後執行。 *replace:install事件執行完成後會指定replace onmessage:主線程與worker之間調用傳遞數據的通道 postMessage:同webworkers相似,用於進行數據傳遞,canary版本不支持。stable反而支持
...還有一些感受不經常使用的就不列出了
如今要使用serviceWorkers實現請求轉發,詳見代碼中的的 urlredirect/下代碼
sw.js(serviceworker)中實現了對9.url.cn的請求所有轉發請求返回一張圖片,即把bg-logo.png換成另外一張220尺寸的圖片。 更多栗子見附件所示。
再來個onmessage的栗子,詳見代碼中的的 postMessage/下代碼:
其實這個就和webworker同樣了,能夠理解,serviceWorker能夠認爲是一種改進後的webWorker。webworker作的是多線程,serviceworker則是用webworker作了個與網絡請求相關封裝,來監聽一些網絡事件。固然serviceworker也能夠來作不少事情,例如離線緩存應用,甚至替代fiddler做爲調試工具。 目前serviceworker的草案還在更新中,部分api僅在FF nightly和chrome canary中使用,相對還須要較大的完善。
處於安全考慮,serviceworker通常用在https上,緣由有幾點: *防止人爲中間層攻擊 *推進https使用 *開發工具能夠比較自由安全 *https將來會在web中愈來愈普遍 另外serviceworker通常不能放在cdn上,可是能夠經過importscript()來導入cdn上的資源,
根據10月草案,serviceworker將來可能會增長後臺同步,任務調度和消息推送API。
基於serviceworker,chrome canary版本 (chrome37穩定版的好像不行) 在網絡不可用時會顯示小恐龍冒險的離線遊戲,按下空格鍵,就能夠開始呵呵了~~無聊的童鞋能夠去試試,若是本身能作個飛機大戰就更好了。
將來的web 應用將是離線可用的,並且是可以增量更新的,尤爲是在PC客戶端的應用
目前主要的webapp緩存解決方案主要有如下4種,你們一看都懂,這裏只是過一下
3.2.1 基於瀏覽器頭信息的緩存方式 這種方式的緩存過程以下:
說白了,使用瀏覽器頭信息緩存的主要有了兩種,一種是判斷靜態資源http頭部的Etag和Last-Modified是否修改,修改則從新請求,不然忽略;固然還有一種根據expires過時時間來判斷的,原理同樣,可是這兩種方法都必不可少的至少會產生大量http請求,即便返回304。並且一旦離線,瀏覽器就機關用盡了。
3.2.2 使用APP Cache
html5提供了App cache來解決靜態文件存儲的問題,它經過將要緩存的靜態文件聲明在一個manifest文件清單裏,而後在要緩存的html裏經過manifest屬性關聯清單文件便可在下次載入html時優先加載緩存清單中列出的靜態文件。相對於瀏覽器 默認的土鱉方法,靜態文件的緩存變得更加可控了。
可是,有些問題依然有些棘手:
對manifest文件更新,會從新請求全部文件,實際上可能只更新了不多量文件。( 雖然從新請求資源會返回304, 但每一個文件還會發起請求,仍是發起了網絡請求)、針對此點能夠只更新須要更新的文件, 好比能夠創建一個文件版本或者MD5映射,對相同版本或者MD5再也不請求。
manifest文件每次都會請求,咱們能夠按照必定時間更新一次,或者啓動時更新一次,但一旦改變動新就是全量更新
固然也能夠在打開app以前預緩存,提早下載文件或者更新manifest文件。
但這些解決方案,是否是仍然以爲很麻煩,並且依然會有大量的304請求,有木有。
3.2.3 使用localstorage存儲
html5支持的,現對於cookie的確豐富了許多,也擴大了容量,方便易用的API也被普遍接受,可是幾個問題: 一是沒法對靜態文件進行存儲,二是大小限制,雖然各個瀏覽器的localstorage最大容量限制也不同,可是最大的也只是IE9下的7MB,因此要應對離線應用,localstorage仍然是捉襟見肘。
3.2.4 indexedDB緩存
原理提及來比較簡單,IndexedDB的作法是,把一些數據存儲到瀏覽器的indexedDB中,當與網絡斷開時,能夠從瀏覽器中讀取數據,用來作一些離線應用,並且不須要你去寫特定的sql語句來對數據進行操做,它是nosql的,數據形式使用的是json。這種存儲數據的方式彷佛無懈可擊,容量足夠,存取自由,可是對於靜態文件就極其麻煩了。
它能夠是瀏覽器提供給用戶的一個上網代理,經過fetch攔截到用戶的所用請求,能夠不向服務器發送,並能夠將請求轉向本地緩存或其它資源文件的加載,不管是數據仍是靜態文件,而後能夠經過javascript的操做進行增量更新應用數據,並且同時不阻塞瀏覽器的渲染進程。這就很好的解決了咱們的問題。雖然目前瀏覽器支持的程度比較差,可是瀏覽器的發展速度會很快讓咱們用到它的。
(1) webworker 如今能夠在瀏覽器端作多線程操做,但比較限制
(2) serviceworker是在webworker基礎上實現的,它可認爲是使用了webworker技術來處理網絡請求、響應等方面的事務
(3) 二者目前瀏覽器兼容性很很差,尤爲是serviceworker,草案在更新,特性沒有完整,chrome的各分支版本支持都不同,但仍然仍是能夠根據這些特性進行一些有趣的開發。
(4)serviceworker能夠帶給咱們不少
參考文檔 https://jakearchibald.github.io/isserviceworkerready/ (api支持性現狀介紹) http://www.serviceworker.org/# (git主頁) http://www.w3.org/TR/2014/WD-service-workers-20140508/#introduction (w3c介紹) http://jakearchibald.com/2014/service-worker-first-draft/ (serviceWorker草案) https://github.com/jakearchibald/isserviceworkerready (樣例代碼) https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ (10月份更新的草案)