webWorker多线程调用

webWorker多线程调用

1.webWorker多线程可最大程度调用cpu,调用计算机的多个核心同时工作
2.不会阻塞主线程, js线程与gui进程并行
3.计算密集型或高延迟的任务

知识点

浏览器中会存在如下这些进程

浏览器主进程: 负责协调、主控、只有一个 GPU进程:用于3D绘制,可以禁用,只有一个
第三方进程: 每种类型的插件对应一个进程,仅当使用该插件时才创建
渲染进程: 浏览器渲染进程(render进程),即通常说的浏览器内核,主要作用是:页面渲染、脚本执行、事件处理等。每一个标签页的打开都会创建一个Render进程,并且互不影响。默认的话一个标签页对应一个Render进程,但是,有时候浏览器会将多个进程合并,如打开了多个空白标签页。

此外还会存在很多线程,如:
GUI渲染线程: 主要负责渲染浏览器界面,解析HTML,CSS,构建DOM树和Render树,布局和绘制、以及回流重绘等。
JS引擎线: JS引擎线程也称为JS内核,负责处理Javascript脚本程序,解析Javascript脚本,运行代码。
事件触发线程: 事件触发线程归属于浏览器,而不是属于JS引擎,JS引擎处理的事务过多,需要浏览器另开线程来进行协助
定时器触发线程: 即setInterval与setTimeout所在线程
异步http请求线程: XMLHttpRequest连接后通过浏览器新开一个线程请求 worker线程

其中GUI渲染线程和JS引擎线程是互斥的,他们会共用渲染进程,当JS引擎执行时,GUI线程就会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时,才会被执行。
.
举一个简单的小例子,比如咱们通过requestAnimationFrame这个api每16.6ms获取一次时间,并且渲染。当JS引擎线程繁忙的时候,GUI线程就会被挂起,即不会更新咱们页面上的时间,从而导致卡顿的现象。

应用场景

1.大文件分片上传
2.excel大文件导出
3.图片批量压缩
4.canvas绘制
5.音视频渲染

使用方法

worker.postMessage: 向 worker 的内部作用域发送一个消息,消息可由任何 JavaScript 对象组成
worker.terminate: 立即终止 worker。该方法并不会等待 worker 去完成它剩余的操作;worker 将会被立刻停止
worker.onmessage: 当 worker 的父级接收到来自其 worker 的消息时,会在 Worker 对象上触发message 事件
worker.onerror: 当 worker 出现运行中错误时,它的 onerror事件处理函数会被调用。它会收到一个扩展了 ErrorEvent 接口的名为 error 的事件

代码示例

Html

<!DOCTYPE html>
<html lang="en"><head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>web worker</title>
</head><script>
    const number = 20 // 运行次数

    // 多线程测试
    function workerTest() {
    
    
        console.log('%c 开始多线程测试 ', 'color:#fff; background:#00897b ')
        const workerList = []
        for (let i = 0; i < number; i++) {
    
    
            const workerItem = new Promise((resolve, reject) => {
    
    
                const myWorker = new Worker('./worker.js')
                myWorker.postMessage({
    
    
                    function: 'fb',
                    data: 43
                })
                myWorker.onmessage = (e) => {
    
    
                    resolve(e.data)
                    // 关闭worker线程
                    myWorker.terminate()
                }
            })
            workerList.push(workerItem)
        }
        console.time('worker多线程执行时间')
        Promise.all(workerList).then(res => {
    
    
            console.log(res)
            console.timeEnd('worker多线程执行时间')
        })
    }

    function singleTest() {
    
    
        console.log('%c 开始单线程测试 ', 'color:#fff; background:#00897b ')
        function fb(n) {
    
    
            if (n === 1 || n === 2) {
    
    
                return 1;
            }
            return fb(n - 1) + fb(n - 2)
        }
        console.time('单线程执行时间')
        for (let i = 0; i < number; i++) {
    
    
            const res = fb(43)
            console.log({
    
    
                data: res,
                name: 'single test'
            })
        }
        console.timeEnd('单线程执行时间')
    }
</script><body>
    <button onclick="singleTest()">单线程测试</button>
    <button onclick="workerTest()">多线程测试</button>
</body></html>

worker.js

// 方法对象

const funcObj = {
    
    
  fb: (n) => {
    
    
    if (n === 1 || n === 2) {
    
    
      return 1;
    }
    return funcObj.fb(n - 1) + funcObj.fb(n - 2);
  },
};
// onmessage事件
onmessage = function (e) {
    
    
  const {
    
     data } = e;
  const res = funcObj[data.function](data.data);

  // 将获取的数据通过postMessage发送到主线程
  self.postMessage({
    
    
    data: res,
    name: "worker test",
  });
  self.close();
};

查询客户端线程数

window.navigator.hardwareConcurrency

猜你喜欢

转载自blog.csdn.net/r657225738/article/details/128946952