Web Worker的使用

Web Worker

在JavaScript中,因为是单线程执行,所以如果在执行过程中遇到一个运算量很大的代码块时,就可能会出现阻塞代码的情况。为了解决这个问题,我们可以采用异步来实现这部分代码,此外,也可以采用Web Worker来解决这个问题。
Web Worker通过将代码放在后台来实现,避免了阻塞的问题。浏览器实现Web Worker的形式很多,如多线程,后台进程或运行在其他处理器核心上的进程。
实际上,在页面中新建的Web Worker与原页面的作用域不为同一个作用域,这正是与加载其他js文件不同的地方。

创建

Web Worker可以直接使用new操作符创建,传入要作为worker对象的js文件作为参数

let worker = new Worker('worker.js')

监听发送的数据和回调函数

在使用Web Worker时,我们通过使用postMessage来传输数据,为onmessage设置回调函数来对发送的数据做响应处理。

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        let worker = new Worker("worker.js")
        // 往worker对象发送一个对象数据
        worker.postMessage({
            msg: 'here is index.html'
        })
    </script>
</body>

</html>
// worker.js
self.onmessage=event=>{
    // 数据放在响应对象的data属性中
    console.log(event.data)
}

在Web Worker中,全局对象是self,所以这里通过给self的onmessage设置回调函数来监听原页面的作用域发送的数据,当然,这里也可以通过this来设置,因为默认情况下this指向全局对象(非严格模式下)
同样的,在worker中也通过postMessage来向原页面的作用域发送数据,在原页面的作用域中通过worker对象的onmessage来监听发送到当前作用域的数据

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        let worker = new Worker("worker.js")
        // 往worker对象发送一个对象数据
        worker.postMessage({
            msg: 'here is index.html'
        })
        worker.onmessage=event=>{
            console.log(event.data)
        }
    </script>
</body>

</html>
// worker.js
self.onmessage=event=>{
    // 数据放在响应对象的data属性中
    console.log(event.data)
}
self.postMessage({
    msg:'here is worker.js'
})

在这里插入图片描述

Worker线程的关闭

Web Worker给我们带来便利性的同时,也带来了一些问题,如果开启过多的Web Worker,无疑会对性能造成不小的损耗,所以我们必须在Worker线程失去作用时手动关闭Worker线程。

Worker线程的关闭可以在创建Web Worker的地方关闭,也可以在其作用域中关闭

在原页面中,通过terminate方法关闭

worker.terminate()

而在Worker的作用域中,通过调用close方法来关闭

self.close()

在Web Worker引入脚本

如果我们在Web Worker中要引入其他脚本,可以通过importScripts来引入,该方法传入多个参数,每个参数代表要引入的脚本的url,以字符串形式传入

// worker.js
importScripts('file1.js','file2.js');
// file1.js
console.log('file1.js')
// file2.js
console.log('file2.js')

这样就会在页面中输出“file1.js”和“file2.js”,引入脚本的执行严格按照传入参数的先后顺序,即使后面的脚本先于前面的脚本加载完,也依然会按先后顺序来执行脚本。

要注意的是,Web Worker中引入的脚本所在的作用域是Web Worker的作用域,即是说,Web Worker引入脚本实际上等同于我们在页面中引入脚本一样,将脚本带到当前的作用域。

Web Worker的全局作用域

在Web Worker中,全局对象指向self对象,而实际上,这个self指向的是worker对象。我们要清楚的是,Web Worker所执行的JavaScript代码的作用域与当前网页中的代码不共享作用域。
Web Worker只提供了一个“最小”的运行环境,在Web Worker中

  • 无法访问DOM,localStorage,sessionStorage
  • location对象变为只读
  • 最小化的navigator对象,包括onLine,appName,appVersion,userAgent,platform属性
    Web Worker中的navigator对象
    在这里插入图片描述
    原页面中的navigator对象
    在这里插入图片描述
  • XMLHttpRequest构造函数

微信小程序中的Worker对象

微信小程序中同样也有Worker对象
使用createWorker来创建对象,onMessage来监听其他线程发送到当前线程的信息,使用postMessage来向其他线程发送信息,使用terminate来关闭线程
详情见小程序官方文档

发布了178 篇原创文章 · 获赞 12 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/zemprogram/article/details/102767656