- 作者:老汪软件技巧
- 发表时间:2024-09-17 15:03
- 浏览量:
Web Workers
script中的async和defer
Web Workers可以为Web内容在后台线程中运行脚本提供了一种简单的方式,可以实现多线程.在进入到正文之前,我们先看一下这个问题,我们都知道js代码会阻塞html的渲染,那么我们如何解决呢?
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="https://unpkg.com/vue@3/dist/vue.global.js">script>
head>
<body>
<div id="app">
<h2>helloh2>
div>
body>
html>
我们这里请求一份js资源,代码从上到下开始执行,最开始是浏览器的渲染引擎开始工作的,遇到script之后,V8引擎就会开始工作,浏览器渲染引擎就会终止工作,直到V8引擎工作结束,浏览器渲染引擎就继续工作.
那么这里我们有两种方式可以解决这个问题,一个是添加async属性,这一个属性会让js的加载变成异步,浏览器在加载js资源的同时会渲染html.
第二个就是添加defer属性,这个属性也是让js的加载变成异步,但是js资源加载完毕之后,不会立即执行js而是等待html渲染完毕之后再执行.
这里画一份简陋的图来表示
async和defer的共同点都是让js代码异步加载,但是对于async来说html渲染和js加载资源完毕并执行是同时进行的,而defer则是将js资源加载完毕后,等到html渲染完毕之后,js代码部分才会执行
正文
现在我们使用Web Workers来实现图片的预加载
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<h2>图片预加载h2>
<div id="pic">
div>
div>
<script>
let picBox = document.getElementById('pic')
let arr = [
"https://t7.baidu.com/it/u=2604797219,1573897854&fm=193&f=GIF",
"https://t7.baidu.com/it/u=2942499027,2479446682&fm=193&f=GIF",
"https://t7.baidu.com/it/u=3165657288,4248157545&fm=193&f=GIF",
"https://t7.baidu.com/it/u=3240224891,3518615655&fm=193&f=GIF",
"https://t7.baidu.com/it/u=2501476447,3743798074&fm=193&f=GIF"
]
const worker = new Worker('./image.js')
worker.postMessage(arr)
worker.onmessage = function(event) {
console.log('主线程:', event);
const img = new Image()
img.src = window.URL.createObjectURL(event.data)
picBox.appendChild(img)
}
script>
body>
html>
数组arr中存放的是我们需要预加载的图片.const worker = new Worker('./image.js')会为我们创建一个子线程.image.js脚本代码开辟一个新的线程.我们通过postMessage()方法将数组传给子线程.在子线程中我们需要获取到主线程传过来的参数.
self.onmessage = function(event){
console.log(event);
}
self是一个全局对象,代表Worker自身,通过onmessage()监听信息,该方法接受事件参数event
我们在主线程传过来的数组的内容也就在事件参数中,我们可以通过event.data获取到该数组.我们获取到了该数组,也就代表着我们可以拿到图片对应的url地址.通过url加载图片.
for(let i = 0;i
let xhr = new XMLHttpRequest();
xhr.open("GET", event.data[i], true);
xhr.responseType = 'blob'
xhr.onreadystatechange = function(){
if(xhr.readyState===4 && xhr.status==200){
self.postMessage(xhr.response);
}
}
xhr.send();
}
我们通过for循环遍历数组event.data拿到url通过发送axios请求加载资源,xhr.responseType = 'blob'将图片资源加载成blob也就是加载成流的形式的文件.最后返回给主线.
worker.onmessage = function(event) {
console.log('主线程:', event);
const img = new Image()
img.src = window.URL.createObjectURL(event.data)
picBox.appendChild(img)
}
在主线程中也是通过onmessage监听信息,拿到子线程处理过后的资源.
总结
Web Workers的工作流程其实也是非常的简单.通过new Workers创建Workers实例,在主线程中发送消息给子线程,子线程监听主线程消息,完成工作后.子线程将信息传给主线程,主线程监听子线程的信息,主线程拿到信息后再进行操作.简陋的流程图如下: