Web Worker没有使用场景?那只是你没有用到而已
点击关注公众号,回复”福利”
即可参与文末抽奖
前几天的一场面试中,被面试官吐槽了一下,我在我项目中直接使用 Prettier 来做代码格式化,首先加载该依赖包就需要一定的成本了,况且格式化的过程中可能需要一些计算,会导致阻塞整个浏览器。
在这里,我个人目前能想到的就两种方案,一种是使用网络请求的方式,也就是将这个问题抛给后端去处理,后端处理的话也是用相同的办法去做,只是最终把结果返回给前端。因为在浏览器的事件循环中,网络请求并不会阻塞 js 主线程。
还有一个方法就是使用 web worker,将需要格式化或转换的代码交给 worker 去处理,处理完成之后最终把结果返回。
什么是 Web Worker
Web Worker 是一种在浏览器中运行 JavaScript 代码的机制,它允许您在后台线程中执行一些任务,而不会阻塞主线程。主线程通常用于处理用户界面的交互和渲染,而 Web Worker 可以用于执行一些耗时的计算、网络请求、数据处理等任务,以提高应用的性能和响应速度。
它的主要特点是能进行并行计算,他允许在后台同时运行多个线程,这些线程可以并行执行任务。这使得可以同时处理多个耗时的操作,而不会阻塞用户界面。
Web Worker 的使用
首先,您需要创建一个单独的 JavaScript 文件,这将是我们的 Web Worker 文件。例如,我们可以创建一个名为 worker.js 的文件,并编写如下代码:
// worker.js
self.addEventListener("message", (event) => {
// 在这里执行后台任务
const data = event.data;
const result = doSomeHeavyWork(data);
self.postMessage(result);
});
function doSomeHeavyWork(data) {
// 执行耗时的计算或任务
return data * 2;
}
在主线程代码 JavaScript 代码中,我们可以创建一个 Web worker 实例,然后通过消息传递与他进行通信:
// 在主线程中
const worker = new Worker("worker.js");
// 发送消息到 Web Worker
worker.postMessage(42);
// 监听从 Web Worker 返回的消息
worker.addEventListener("message", (event) => {
console.log("接收到 web worker 返回的信息:", event.data);
worker.terminate();
});
在上述的代码中,使用 addEventListener 监听 message 事件,然后在事件处理程序中执行后台任务。使用 self.postMessage 向主线程发送结果。
在主线程代码中,可以通过使用 postMessage 方法向 Web Worker 发送消息。
最终代码允许结果如下所示:
如何在项目中使用
首先先来说明一下的我自己的情况,我最终在开发一个在线代码协同编辑器,Github 地址 在整个项目中,我们难免会用到一些代码转换或者代码格式化,那么我们这里可以通过使用 Web Worker 的方式来对其进行处理,最终把结果返回给 JavaScript 主线程。
❝在这篇文章中我们主要是讲解如何将 scss 代码转换成 css 代码。
❞
要想使用,我们首先需要 sass 模块:
pnpm add sass
首先我们创建一个 compiler.ts
文件作为 worker 文件,代码如下所示:
import * as sass from "sass";
self.onmessage = (event) => {
const scssCode = event.data;
try {
const result = sass.compileString(scssCode);
self.postMessage({ compiledCss: result.css });
} catch (error: any) {
self.postMessage({ error: error.message });
}
};
它接收从主线程发送的 SCSS 代码,使用 sass 包进行编译,然后将编译后的 CSS 或错误消息发送回主线程。
在我们的 App.tsx
文件中编写以下代码,如下所示:
import React, { useState } from "react";
const App = () => {
const [scssCode, setScssCode] = useState<string>(
`
$primary-color: #3498db;
.button {
background-color: $primary-color;
color: white;
padding: 10px 20px;
border: none;
cursor: pointer;
&:hover {
background-color: darken($primary-color, 10%);
}
}
`
);
const compileScss = () => {
if (!scssCode) return;
const worker = new Worker(new URL("./compiler.ts", import.meta.url), {
type: "module",
});
worker.onmessage = (event) => {
if (event.data.error) {
console.error(event.data.error);
} else {
setScssCode(event.data.compiledCss);
}
worker.terminate();
};
worker.postMessage(scssCode);
};
return (
<div>
<code
style={{
background: "black",
color: "white",
height: "200px",
width: "200px",
display: "block",
}}
>
{scssCode}
</code>
<button onClick={compileScss}>编译代码</button>
</div>
);
};
export default App;
在这段代码中我主要做的事情是我偷了个懒哈哈哈哈哈。
我把我们要编写的 scss 代码事先编写好了并通过 worker.postMessage(scssCode)
的方式向 web worker
发送 scss 源代码,并使用 worker.onmessage = event => { ... }
来监听 Web Worker 返回的消息。如果返回的消息包含编译后的 CSS,则更新 scssCode 的状态以显示编译后的 CSS。
首先请看原图,这是我们没有编译过的代码,如下图所示:
当我们点击编译按钮,它会显示被编译后的代码,也就是 css 代码:
大功告成,这个方法运用得好,说不定就成为了你项目中的亮点呢。
总结
通过这种实现方式结合了前端技术,为用户提供了一个简单的在线 SCSS 编译工具。通过将耗时的编译操作放在 Web Worker 中执行,保持了用户界面的流畅性,并提供了实时的编译反馈。
点击小卡片,参与粉丝专属福利!!