Web worker,service worker和worklet。所有这些就是我所说的“ Javascript Workers”,尽管它们在worker方式上确实有一些相似之处,但是它们在用途上几乎没有重叠。
广义上讲,web worker是在与浏览器页面线程分开的线程上运行的脚本。通过<script>
标记的HTML文档中包含的是典型Javascript,该文件将在页面线程上运行。如果页面线程上的活动过多,则会降低站点速度,使交互变得紧张而无响应。
Web Worker,Service Worker和Worklet都是在单独线程上运行的脚本。那么这三种类型有什么区别?
web worker
web worker是最通用的worker类型。正如我们将在下面看到的,与service worker和worklet不同,它们没有特定的用例,除了可以与页面线程分开运行之外。因此,Web Worker可以用于从页面线程分流几乎所有繁重的处理。
Web worker与页面线程分离的图,其中postMessage作为通信Web worker是使用来创建的Web Workers API
。为我们的worker人员创建专用的Javascript文件后,我们可以将其添加为新的Worker
。
/* main.js */
const myWorker = new Worker('worker.js');
这将开始运行worker.js
文件中包含的所有代码。正如我提到的,这几乎可以是任何东西,但是Web worker对于卸载可能需要很长时间或与其他进程并行运行的进程非常有用。图像处理Web应用程序Squoosh是一个很好的例子,它使用Web worker来处理图像处理任务,而页面线程可供用户与应用程序交互而不会中断。
与所有web worker一样,Webweb worker也无权访问DOM,这意味着必须在web worker和页面脚本之间使用传递所需的任何信息window.postMessage()
。
/* main.js */
// Create worker
const myWorker = new Worker('worker.js');
// Send message to worker
myWorker.postMessage('Hello!');
// Receive message from worker
myWorker.onmessage = function(e) {
console.log(e.data);
}
在worker脚本中,我们可以监听来自页面脚本的消息,并返回结果。
/* worker.js */
// Receive message from main file
self.onmessage = function(e) {
console.log(e.data);
// Send message to main file
self.postMessage(workerResult);
}
service worker
service worker是一种专门用于浏览器与网络和/或缓存之间的代理。
与辅助线程分离的service worker图,以postMessage作为通信。service worker还与服务器和缓存进行了通信。与web worker一样,service worker在页面javascript文件中注册,引用了专用的service worker文件。
/* main.js */
navigator.serviceWorker.register('/service-worker.js');
与常规的Web worker不同,service worker具有一些额外的功能,使他们可以实现其代理目的。一旦安装并激活它们,service worker就可以拦截从页面文档发出的任何网络请求。
/* service-worker.js */
// Install
self.addEventListener('install', function(event) {
// ...
});
// Activate
self.addEventListener('activate', function(event) {
// ...
});
// Listen for network requests from the main document
self.addEventListener('fetch', function(event) {
// ...
});
一旦被拦截,service worker可以例如通过从缓存中返回而不是进入网络来做出响应,从而使Web应用程序能够离线运行!
/* service-worker.js */
self.addEventListener('fetch', function(event) {
// Return data from cache
event.respondWith(
caches.match(event.request);
);
});
worklet
worklet是一个非常轻量级的,高度特定的worker。它们使我们作为开发人员能够参与浏览器渲染过程的各个部分。
呈现网页时,浏览器将经历许多步骤,这里我们需要担心四个步骤-样式,布局,绘画和合成。
浏览器管道-从Javscript到样式到布局再到绘画到合成让我们进入绘画阶段。这是浏览器将样式应用于每个元素的地方。挂接到此渲染阶段的worker项是Paint Worklet。
Paint Worklet允许我们创建自定义图像,这些图像可以应用于CSS期望图像的任何位置,例如,作为background-image
属性的值。
与所有worker人员一样,要创建一个worklet,我们会在页面javascript文件中注册它,并引用专用的worklet文件。
/* main.js */
CSS.paintWorklet.addModule('myWorklet.js');
在我们的worker文件中,我们可以创建自定义图像。该paint
方法的worker原理与Canvas API非常相似。这是一个简单的黑白渐变示例。
/* myWorklet.js */
registerPaint('myGradient', class {
paint(ctx, size, properties) {
var gradient = ctx.createLinearGradient(0, 0, 0, size.height / 3);
gradient.addColorStop(0, "black");
gradient.addColorStop(0.7, "rgb(210, 210, 210)");
gradient.addColorStop(0.8, "rgb(230, 230, 230)");
gradient.addColorStop(1, "white");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, size.width, size.height / 3);
}
});
最后,我们可以在CSS中使用这个新worklet,并且我们创建的自定义图像将像其他任何背景图像一样被应用。
div {
background-image: paint(myGradient);
}
除了Paint Worklet之外,还有其他worker项可以挂接到渲染过程的其他阶段。Animation Worklet挂钩到合成阶段和Layout Worklet到布局阶段。
回顾
概括地说,Web Worker,Service Worker和Worklet都是在与浏览器页面线程不同的线程上运行的脚本。它们的不同之处在于它们的使用位置以及启用这些用例所必须具备的功能。
worklet与浏览器的渲染管道挂钩,使我们能够对浏览器的渲染过程(例如样式和布局)进行低级访问。
service worker是浏览器和网络之间的代理。通过拦截文档发出的请求,service worker可以将请求重定向到缓存,从而实现脱机访问。
Web Worker是通用脚本,使我们能够从页面线程上卸载处理器密集型worker。
网友评论