webworker的灵活应用

相信大家已经知道了webworker,这里就不多赘述了。

但是我发现了一个问题,就是很多文章在介绍webworker的时候,worker.js里面的内容都是写死的,然后前端页面直接获取数据。但是更多情况下,我们也不知道worker要做什么,只是希望能够借助它作为多线程的计算能力,而不阻塞主线程。那么能不能在主线程写个函数,然后交给worker去计算?于是我尝试了一下

首先是不用worker的代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            div {
                width: 100px;
                height: 100px;
                background-color: red;
            }
        </style>
    </head>
    <body>
        <div></div>
        <script>
            function fn() {
                let count = 0
                for (let i = 0; i < 10000000000; i++) {
                    count++
                }
                return count
            }
        console.log(fn())
        </script>
    </body>
</html>

我们可以看到,页面卡了很久,才把红色的方块渲染出来。而使用worker,把fn作为参数传过去怎样?修改代码:

js 复制代码
// script
            const worker = new Worker('./worker.js')
            worker.postMessage(fn)
            function fn() {
                let count = 0
                for (let i = 0; i < 10000000000; i++) {
                    count++
                }
                return count
            }
            worker.onmessage = ({ data }) => {
                console.log(data)
            }
            
// worker.js
onmessage = (e) => {
    const fn = e.data
    const data = fn()
    postMessage(data)
}

但是页面就报错了

查了一下发现,原来postMessage只能传数字、字符串、布尔值、普通类型数组或普通类型对象。到这里好像没办法了,但是我想到了eval,就是把函数当成字符串传过去,再由worker用eval去执行。于是重新修改代码:

js 复制代码
//html
            const worker = new Worker('./worker.js')
            worker.postMessage(`(${fn})()`)
            function fn() {
                let count = 0
                for (let i = 0; i < 10000000000; i++) {
                    count++
                }
                return count
            }
            worker.onmessage = ({ data }) => {
                console.log(data)
            }

// worker.js
onmessage = (e) => {
    const data = eval(e.data)
    postMessage(data)
}

我们可以看到结果出来了

并且不依赖于worker.js的内容了,只把它当成一个多线程的计算工具,前端想用它来计算什么,就传什么。比如我们再添加一个函数test

js 复制代码
            const worker = new Worker('./worker.js')
            worker.postMessage(`(${fn})()`)

            function fn() {
                let count = 0
                for (let i = 0; i < 10000000000; i++) {
                    count++
                }
                return count
            }

            function test() {
                let count = 0
                for (let i = 0; i < 7777777777; i++) {
                    count++
                }
                return count
            }
            worker.postMessage(`(${test})()`)
            worker.onmessage = ({ data }) => {
                console.log(data)
            }

完美计算出来

如果并发的任务很多,且每一个的计算量都很大,而我们只需要获取最终的结果。我们就可以写多个worker文件,比如worker1.js、worker2.js文件,相当于开启多个线程,然后把任务传入不同的worker中计算。

相关推荐
知识分享小能手8 小时前
uni-app 入门学习教程,从入门到精通,uni-app组件 —— 知识点详解与实战案例(4)
前端·javascript·学习·微信小程序·小程序·前端框架·uni-app
苏打水com8 小时前
从 HTML/CSS/JS 到 React:前端进阶的平滑过渡指南
前端·javascript·html
一枚前端小能手8 小时前
🔐 单点登录还在手动跳转?这几个SSO实现技巧让你的用户体验飞起来
前端·javascript
tianchang8 小时前
深入理解 JavaScript 异步机制:从语言语义到事件循环的全景图
前端·javascript
JNU freshman9 小时前
vue 技巧与易错
前端·javascript·vue.js
Asort9 小时前
JavaScript设计模式(十六)——迭代器模式:优雅遍历数据的艺术
前端·javascript·设计模式
我是日安9 小时前
从零到一打造 Vue3 响应式系统 Day 28 - shallowRef、shallowReactive
前端·javascript·vue.js
开源之眼9 小时前
深入理解 JavaScript 报错:TypeError: undefined is not a function
前端·javascript
却尘10 小时前
当你敲下 `pnpm run dev`,这台机器到底在背后干了什么?
前端·javascript·面试
歪歪10010 小时前
React Native开发有哪些优势和劣势?
服务器·前端·javascript·react native·react.js·前端框架