1.创建 Worker
通过 new 的方式来生成一个实例,参数为 url 地址,该地址必须和其创建者是同源的。
const worker = new Worker('./worker.js'); // 参数是url,这个url必须与创建者同源2. Worker 的方法
const worker = new Worker('./worker.js'); worker.onmessage = function (messageEvent) { console.log(messageEvent) }onmessageerror 主线程中可以在 Worker 上添加 onmessageerror 方法,用于监听 Worker 的错误信息。
const worker = new Worker('./worker.js'); worker.onmessageerror = function (messageEvent) { console.log(messageEvent) }postMessage() 主线程通过此方法给 Worker 发送消息,发送参数的格式不限(可以是数组、对象、字符串等),可以根据自己的业务选择。
const worker = new Worker('./worker.js'); worker.postMessage({ type: 'start', payload: { count: 666 } }); // 发送信息给workerterminate() 主线程通过此方法终止 Worker 的运行。
const worker = new Worker('./worker.js'); worker.terminate();3.通信
// 监听事件,主线程可以通过 postMessage 发送信息过来 self.onmessage = (messageEvent) => { const { type, payload } = messageEvent.data; switch (type) { case 'start': // 通过 type 去区分不同的业务逻辑,payload 是传过来的数据 const result = 0; // ....,通过一系列处理之后,把最终的结果发送给主线程 this.postMessage(result); break; } };这里我们从 messageEvent.data 中获取从主线程传递过来的数据。为了业务的扩展性,这边是以 type 去区分不同的业务,payload 承载数据源,通过处理之后把结果发给主线程。主线程的 onmessage 回调函数中就能收到这个结果了。
// Worker.js importScripts('constant.js'); // 下面就可以获取到 constant.js 中的所有变量了 // constant.js // 可以在 Worker 中使用 const a = 111; // 不可以在 Worker 中使用,原因未知 const b = function () { console.log('test'); }; // 可以在 Worker 中使用 function c() { console.log('test'); }5.调试方法
const worker = new SharedWorker("./shareWorker.js"); // 参数是url,这个url必须与创建者同源2.SharedWorker 的方法
const sharedWorker = new SharedWorker('./shareWorker.js'); sharedWorker.port.onmessage = function (messageEvent) { console.log(messageEvent) }port.postMessage()
const sharedWorker = new SharedWorker('./shareWorker.js'); sharedWorker.port.postMessage({ type: 'increase', payload: { count: 666 } });port.start()
const sharedWorker = new SharedWorker('./shareWorker.js'); sharedWorker.port.start()port.close()
const sharedWorker = new SharedWorker('./shareWorker.js'); sharedWorker.port.close()3.通信
// index.js const worker = new SharedWorker('./shareWorker.js'); worker.port.start(); // 开启端口 // 发送信息给shareWorker worker.port.postMessage({ type: 'increase', payload: { count: 666 } }); // 接受shareWorker发过来的数据 worker.port.onmessage = function (val) { console.log(val.data) }; // shareWorker.js let count = 666; port.onmessage = (messageEvent) => { const { type, payload } = messageEvent.data; switch (type) { case 'increase': port.postMessage(++count); break; case 'decrease': port.postMessage(--count); break; } };4.Worker 中引用其他脚本
// index.js if ('serviceWorker' in navigator) { window.addEventListener('load', function () { navigator.serviceWorker .register('./serviceWorker.js', { scope: '/page/' }) .then( function (registration) { console.log( 'ServiceWorker registration successful with scope: ', registration.scope ); }, function (err) { console.log('ServiceWorker registration failed: ', err); } ); }); }只要创建了 ServiceWorker,不管这个创建 ServiceWorker 的 html 是否打开,这个 ServiceWorker 是一直存在的。它会代理范围是根据 scope 决定的,如果没有这个参数,则其代理范围是创建目录同级别以及子目录下所有页面的网络请求。代理的范围可以通过registration.scope 查看。
// serviceWorker.js const CACHE_NAME = 'cache-v1'; // 需要缓存的文件 const urlsToCache = [ '/style/main.css', '/constant.js', '/serviceWorker.html', '/page/index.html', '/serviceWorker.js', '/image/131.png', ]; self.oninstall = (event) => { event.waitUntil( caches .open(CACHE_NAME) // 这返回的是promise .then(function (cache) { return cache.addAll(urlsToCache); // 这返回的是promise }) ); };在上述代码中,我们可以看到,在 install 事件的回调中,我们打开了名字为 cache-v1 的缓存,它返回的是一个 promise。在打开缓存之后,我们需要把要缓存的文件 add 进去,基本上所有类型的资源都可以进行缓存,例子中缓存了 css、js、html、png。如果所有缓存数据都成功,就表示 ServiceWorker 安装成功;如果控制台提示 Uncaught (in promise) TypeError: Failed to execute 'Cache' on 'addAll': Request failed,则表示安装失败。
self.onfetch = (event) => { event.respondWith( caches .match(event.request) // 此方法从服务工作线程所创建的任何缓存中查找缓存的结果 .then(function (response) { // response为匹配到的缓存资源,如果没有匹配到则返回undefined,需要fetch资源 if (response) { return response; } return fetch(event.request); }) ); };在 fetch 事件的回调中,我们去匹配 cache 中的资源。如果匹配到,则使用缓存资源;没有匹配到则用 fetch 请求。正因为 ServiceWorker 可以代理网络请求,所以为了安全起见,规范中规定它只能在 https 和 localhost 下才能开启。