Web Worker没有使用场景?那只是你没有用到而已

前端瓶子君

共 4446字,需浏览 9分钟

 ·

2023-10-10 12:25

点击关注公众号,回复”福利” 

即可参与文末抽奖

前几天的一场面试中,被面试官吐槽了一下,我在我项目中直接使用 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 发送消息。

最终代码允许结果如下所示:

20230814083307

如何在项目中使用

首先先来说明一下的我自己的情况,我最终在开发一个在线代码协同编辑器,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。

首先请看原图,这是我们没有编译过的代码,如下图所示:

20230814085751

当我们点击编译按钮,它会显示被编译后的代码,也就是 css 代码:

20230814085838

大功告成,这个方法运用得好,说不定就成为了你项目中的亮点呢。

总结

通过这种实现方式结合了前端技术,为用户提供了一个简单的在线 SCSS 编译工具。通过将耗时的编译操作放在 Web Worker 中执行,保持了用户界面的流畅性,并提供了实时的编译反馈。

点击小卡片参与粉丝专属福利!!



如果文章对你有帮助的话欢迎
「关注+点赞+收藏」

浏览 597
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报