首页  >  文章  >  web前端  >  使用 Web Workers 在 JS 中实现多线程

使用 Web Workers 在 JS 中实现多线程

王林
王林原创
2024-08-16 06:18:02292浏览

Web Worker:一种在与当前主(窗口)线程不同的线程中在后台运行脚本的方法。

  1. Web Worker 与使用 event_loop 的异步
  2. Web Worker 简介
  3. 如何创建网络工作者
  4. 例如网络工作者
  5. Web Workers 的限制
  6. Web Workers 中的异步操作

1. Web Workers 与使用事件循环的异步操作

JavaScript 通常通过将任务放入相应的队列(宏任务队列、微任务队列)来处理异步操作,事件循环不断检查这些队列,并在任务准备好执行时将其推送到调用堆栈中。这种方法确保非阻塞执行,但仍然在单个线程上运行所有内容。

另一方面,

Web Workers 允许脚本在完全独立的线程中运行,具有自己的调用堆栈、异步队列和事件循环。这种分离可以防止主线程被繁重的计算或长时间运行的任务阻塞,因为工作线程独立运行。

2. Web Workers 简介

Web Worker 在与主窗口上下文不同的上下文中执行脚本,从而实现 Web 应用程序中的并行性。 Web Worker API 提供了几种类型的 Worker:

  • Dedicated Workers:由单个脚本使用,这些非常适合从主线程卸载任务。
  • 共享工作线程:可由在不同上下文(例如,不同窗口或 iframe)中运行的多个脚本访问。
  • Service Workers:作为 Web 应用程序、浏览器和网络之间的代理服务器运行,提供离线支持和缓存等功能。

本文重点介绍专用工作者,这是最容易实现且最常用的。

3. 如何创建 Web Worker

要创建 Web Worker,您可以使用以下关键方法:

  • new Worker():创建新worker的构造函数。
  • postMessage():从主线程向工作线程发送消息,反之亦然。
  • onmessage:设置用于处理worker收到的消息的回调函数。
  • terminate():立即停止工作线程。

4. 简单示例

让我们创建一个工作程序来从 API 获取数据,特别是从 Dog CEO API 获取狗图像。

4.1 工人代码

这是工作脚本的实现。请注意,在worker内部,self用于引用全局上下文:

if (window.Worker) {
    const worker = new Worker("/src/worker.js");
        worker.postMessage({ 
            operation: "get_dog_imgs",
            url: "https://dog.ceo/api/breeds/image/random", 
            count: 5   //number of photos
        });
        worker.onmessage = (e) => {
        console.log(e.data);
        if (e && e.data) {
            setdata((old) => [...old, e.data]); // update react state
            showCallStack(); // function to show the callstack 
        }
    };
    worker.onerror = (e) => {
        console.log(e);
    };
}

在此代码中,worker 侦听消息 (onmessage) 并根据计数指定多次从给定 URL 获取数据。

这是工作线程内部的调用堆栈:

MultiThreading In JS using Web Workers

4.2 客户端代码

主线程像这样使用worker:

self.onmessage = (event) => {
    const data = event.data;
    if (data && data.url && data.count) {
        fetchFromUrls(data.url, data.count);
    }
}
// fetch single data 
const fetchdata = async (url) => {
    const res = await self.fetch(url);
    return await res.json();
};

const fetchFromUrls = async (url, count) => {
    showCallStack(); // showing the callstack of the worker 
    for (const i of new Array(count).fill(0)) {
        let data = await fetchdata(url);
        if (data && data.message) {
            self.postMessage({ type: "img", data: data.message });
        }
    }
};

此代码演示了如何向工作线程发送消息并在主线程中接收获取的数据。

MultiThreading In JS using Web Workers

完整代码请访问代码

MultiThreading In JS using Web Workers

5. Web Workers 的局限性

虽然 Web Worker 在与主窗口线程不同的线程中运行,但它们有一定的限制:

  • 无法访问 DOM:Workers 无法直接操作 DOM。更新 UI 需要与主线程通信。
  • 资源消耗:过度使用 Web Worker 可能会导致内存使用率过高,因为每个 Worker 都需要额外的资源才能独立运行。

以上是使用 Web Workers 在 JS 中实现多线程的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn