JavaScript Web Worker 入门:API、上下文与使用限制详解

作者:代码拾荒

时间:2026-10-24

浏览:406

本文详细介绍 JavaScript 中 Web Worker 的使用。涵盖如何创建后台线程处理耗时计算,避免阻塞主线程;解析 postMessage、terminate 等核心 API;说明 Worker 运行在 WorkerGlobalScope 上下文,无法访问 DOM 但支持网络请求与定时器;并列举其跨域、DOM 访问及浏览器兼容性等限制。

文章目录

一、Web Worker 初探

JavaScript 默认采用单线程模型,这一特性有其特定的运行背景。

具体表现如下:


<!DOCTYPE html>
    <head>
        <title>singleThread</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    </head>
    <body>
        <script>
            //添加到任务队列中,待同步任务所处的‘执行栈'执行完毕,1秒后执行任务队列中的这个匿名函数
            setTimeout(function(){
                console.log('come on');
            },1000);
            //只要不关闭该alert,‘执行栈'就没结束,从而也就不会进入到任务队列中
            alert('waiting');
        </script>
    </body>
</html>

HTML5 引入了 Web Worker 机制,允许开发者编写长时间运行的后台程序。这些程序可以执行复杂的逻辑或事务,同时确保页面仍能对用户操作做出即时响应。

简而言之,Web Worker 允许 JavaScript 创建多个线程。然而,子线程完全受主线程控制,且严禁直接操作 DOM。

因此,Web Worker 非常适合用于处理高耗时的计算任务。

以下为主页面的示例代码:


<!DOCTYPE html>
    <head>
        <title>worker</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <script>
            function init(){
                //创建一个Worker对象,并向它传递将在新线程中执行的脚本url
                var worker = new Worker('worker.js');
                //接收worker传递过来的数据
                worker.onmessage = function(event){
                    document.getElementById('result').innerHTML+=event.data+"<br/>" ;
                };
            };
        </script>
    </head>
    <body onload = "init()">
        <div id="result"></div>
    </body>
</html>

以下是 worker.js 文件的内容:


var i = 0;
function timedCount(){
    for(var j = 0, sum = 0; j < 100; j++){
        for(var i = 0; i < 100000000; i++){
            sum+=i;
        };
    };
    //将得到的sum发送回主线程
    postMessage(sum);
};
//将执行timedCount前的时间,通过postMessage发送回主线程
postMessage('Before computing, '+new Date());
timedCount();
//结束timedCount后,将结束时间发送回主线程
postMessage('After computing, ' +new Date());

上述代码的执行流程如下:首先创建 Worker 对象,随后通过 onmessage 方法接收来自 worker.js 中 postMessage 传递的数据(即 event.data),并将接收到的数据追加到 id 为 result 的 div 元素中。

执行上述代码后,结果如下所示:

一、Web Worker 初探

图一

当 worker.js 中的 timedCount 方法运算完成后,会执行 postMessage 操作向主线程传输数据,从而得到图二的结果。在此期间,主线程的运行不受影响。

一、Web Worker 初探

图二

二、Web Worker 常用 API

接下来,我们进一步了解 Worker 相关的常用 API:

1、postMessage(data)

这是子线程与主线程之间相互通信的方法,传递的 data 参数可以是任意类型的值。


//worker = new Worker('url');
//worker.postMessage传递给子线程数据,对象
worker.postMessage({first:1,second:2});

//子线程中也可以使用postMessage,如传递字符串
postMessage(‘test');

2、terminate()

在主线程中调用此方法可终止 Worker。终止后,该 Worker 无法再进行消息传递。注意:一旦调用 terminate,该实例无法重新启用,必须创建新的 Worker 实例。


//worker = new Worker('url');
worker.terminate();

例如,主页面代码:


<!DOCTYPE html>
    <head>
        <title>worker</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <script>
            function init(){
                var worker = new Worker('worker.js');
                //每隔100毫秒,向子线程传递{name: 'monkey'}信息
                setInterval(function(){
                    worker.postMessage({name: 'monkey'});
                },100);
                //当主线程worker收到来自子线程的消息后,触发message事件
                worker.onmessage = function(event){
                    document.getElementById('result').innerHTML+=event.data+"<br/>" ;
                    //主线程使用terminate方法中断与子线程来往,在浏览器中只能显示一次event.data
                    worker.terminate();
                };
            };
        </script>
    </head>
    <body onload = "init()">
        <div id="result"></div>
    </body>
</html>

子线程 worker.js 代码:


//当主线程发来信息后,触发该message事件
onmessage = function(event){
    //向主线程发送event.data.name信息
    postMessage(event.data.name);
};

3、message 事件

当有消息发送时,会触发 message 事件。消息传递是双向的,内容可通过 event.data 获取。

message 事件的具体使用,可参考 terminate 中的示例代码。

4、error 事件

用于处理错误情况。错误信息可通过 event.message 获取。

示例如下:


//worker = new Worker('url');
worker.onerror = function(e){
    //打印出错消息
    console.log(e.message);
    //中断与子线程的联系
    worker.terminate();
}

另外,Worker 线程从上到下同步执行代码,随后进入异步阶段以响应事件及计时器。如果 Worker 注册了 message 事件处理程序,只要该程序有可能被触发,Worker 就会一直驻留在内存中而不会自动退出。因此,通信完毕后需手动在主线程中调用 terminate,或在子线程中调用 close。如果 Worker 没有监听消息,当所有任务(包括计数器)执行完毕后,它会自动退出。

三、Worker 上下文环境

先观察以下代码示例:

主页面代码:


<!DOCTYPE html>
    <head>
        <title>worker</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <script>
            function init(){
                var worker = new Worker('worker.js');
                //接收消息事件
                worker.onmessage = function(event){
                    console.log(event.data);
                };
                //错误信息事件
                worker.onerror = function(e){
                    console.log('erro: ' + e.message);
                    //终止线程
                    worker.terminate();
                };
            };
        </script>
    </head>
    <body onload = "init()">
        
    </body>
</html>

worker.js 代码:


//window对象的alert方法
alert(1);
onmessage = function(event){
    //向主线程发送event.data.name信息
    postMessage(event.data.name);
};

执行上述代码的结果为:

一、Web Worker 初探

出现错误的原因是,alert 是 window 对象的方法,而在 Worker 环境中无法直接访问,因此报错 undefined。

worker.js 的执行上下文与主页面 HTML 的上下文不同。其顶层对象并非 window,而是 WorkerGlobalScope。因此,Worker 无法访问 window 对象及相关 DOM API,但可以与 setTimeout、setInterval 等方法协同工作。

WorkerGlobalScope 作用域下的常用属性和方法如下:

1、self

可以使用 WorkerGlobalScope 的 self 属性来获取该对象本身的引用。

2、location

location 属性返回线程创建时关联的 WorkerLocation 对象,表示初始化该工作线程的脚本资源的绝对 URL。即使页面发生多次重定向,该 URL 资源位置也不会改变。

3、close

用于关闭当前 Worker 线程,作用与 terminate 类似。

4、importScripts

可以通过 importScripts() 方法,利用 URL 在 Worker 中加载外部库函数。

5、XMLHttpRequest

借助此对象,Worker 可以发起 Ajax 请求。

6、setTimeout/setInterval 以及 addEventListener/postMessage

四、关于 Worker 的使用总结

我们可以利用 Worker 实现以下功能:

1. 加载 JS 文件进行大量复杂计算,避免阻塞主进程,并通过 postMessage 和 onmessage 进行通信。

2. 在 Worker 中通过 importScripts(url) 加载其他脚本文件。

3. 使用 setTimeout(), clearTimeout(), setInterval(), 和 clearInterval()。

4. 使用 XMLHttpRequest 发送网络请求。

5. 访问 navigator 的部分属性。

同时,Worker 也存在以下局限性:

1. 不能跨域加载 JS 文件。

2. Worker 内的代码无法访问 DOM。

3. 各浏览器对 Worker 的实现存在差异。例如,Firefox 允许在 Worker 中创建新的 Worker,而 Chrome 则不支持。

4. IE 浏览器对该特性的支持情况需特别注意(注:原文表述模糊,此处保留原意)。

以上是对 Web Worker 的简要介绍,更多详细内容请关注本站其他相关文章。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章