如何通过JS实现Web Worker高效并行处理?

更新于
2026-09-26 12:53:27
2阅读来源:SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1905个文字,预计阅读时间需要8分钟。

如何通过JS实现Web Worker高效并行处理?

目录

一、webWorker 初体验

二、webWorker 常用方法

1. postMessage(data) 2. terminate() 3. message 4. error

三、worker 上文下文

四、关于worker

一、webWorker 初体验 由于JavaScript是单线程的,也是异步的,所以有时我们需要在后台执行一些任务,而不会阻塞主线程。webWorker就是用来实现这个功能的。

二、webWorker 常用方法 1. postMessage(data):向worker发送消息 2. terminate():终止worker 3. message:接收来自worker的消息 4. error:监听worker的错误

三、worker 上文下文 在创建worker时,我们可以传入一个URL,这个URL指向一个JavaScript文件,这个文件中的代码将在worker中执行。

四、关于worker webWorker为JavaScript提供了在后台线程执行代码的能力,使得可以处理耗时任务而不会阻塞主线程。

目录
  • 一、webWorker之初体验
  • 二、webWorker之常用API
    • 1、postMessage(data)
    • 2、terminate()
    • 3、message
    • 4、error
  • 三、worker上下文
    • 四、关于worker

      一、webWorker之初体验

      所以,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引入了一个工作线程(webWorker)的概念。它允许开发人员编写能够长时间运行而不被用户所中断的后台程序,去执行事务或者逻辑,并同时保证页面对用户的响应。

      简而言之,就是允许JavaScript创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。

      从而,可以用webWorker来处理一些比较耗时的计算。

      如下,主页面:

      <!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的内容:

      如何通过JS实现Web Worker高效并行处理?

      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),并将数据追加到div#result中。

      所以,执行上面的代码结果如下:

      图一

      待worker.js中的timedCount方法运算完后,执行postMessage操作,向主线程传数据,得图二。期间,并不影响主线程的运作。

      图二

      二、webWorker之常用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,此后无法再利用其进行消息传递。注意:一旦terminate后,无法重新启用,只能另外创建。

      //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

      当有消息发送时,触发该事件。且,消息发送是双向的,消息内容可通过data来获取。

      message使用,可见terminate中的demo

      4、error

      出错处理。且错误消息可以通过e.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); };

      执行上面代码结果:

      为什么会这样呢?原因是alert为window对象的方法,所以会报错undefined。

      worker.js执行的上下文,与主页面html执行时的上下文并不相同,最顶层的对象并不是window,woker.js执行的全局上下文,是个叫做WorkerGlobalScope的东东,所以无法访问window、与window相关的DOM API,但是可以与setTimeout、setInterval等协作。

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

      1、self

      我们可以使用 WorkerGlobalScope 的 self 属性来或者这个对象本身的引用

      2、location

      location 属性返回当线程被创建出来的时候与之关联的 WorkerLocation 对象,它表示用于初始化这个工作线程的脚步资源的绝对 URL,即使页面被多次重定向后,这个 URL 资源位置也不会改变。

      3、close

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

      4、importScripts

      我们可以通过importScripts()方法通过url在worker中加载库函数

      5、XMLHttpRequest

      有了它,才能发出Ajax请求

      6、setTimeout/setInterval以及addEventListener/postMessage

      四、关于worker

      我们可以做什么:

      1.可以加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信

      2.可以在worker中通过importScripts(url)加载另外的脚本文件

      3.可以使用setTimeout(), clearTimeout(), setInterval(), and clearInterval()

      4.可以使用XMLHttpRequest来发送请求

      5.可以访问navigator的部分属性

      局限性:

      1.不能跨域加载JS

      2.worker内代码不能访问DOM

      3.各个浏览器对Worker的实现不大一致,例如FF里允许worker中创建新的worker,而Chrome中就不行

      4.IE这个新特性

      以上就是浅谈webWorker的详细内容,更多关于浅谈webWorker的资料请关注自由互联其它相关文章!

      本文共计1905个文字,预计阅读时间需要8分钟。

      如何通过JS实现Web Worker高效并行处理?

      目录

      一、webWorker 初体验

      二、webWorker 常用方法

      1. postMessage(data) 2. terminate() 3. message 4. error

      三、worker 上文下文

      四、关于worker

      一、webWorker 初体验 由于JavaScript是单线程的,也是异步的,所以有时我们需要在后台执行一些任务,而不会阻塞主线程。webWorker就是用来实现这个功能的。

      二、webWorker 常用方法 1. postMessage(data):向worker发送消息 2. terminate():终止worker 3. message:接收来自worker的消息 4. error:监听worker的错误

      三、worker 上文下文 在创建worker时,我们可以传入一个URL,这个URL指向一个JavaScript文件,这个文件中的代码将在worker中执行。

      四、关于worker webWorker为JavaScript提供了在后台线程执行代码的能力,使得可以处理耗时任务而不会阻塞主线程。

      目录
      • 一、webWorker之初体验
      • 二、webWorker之常用API
        • 1、postMessage(data)
        • 2、terminate()
        • 3、message
        • 4、error
      • 三、worker上下文
        • 四、关于worker

          一、webWorker之初体验

          所以,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引入了一个工作线程(webWorker)的概念。它允许开发人员编写能够长时间运行而不被用户所中断的后台程序,去执行事务或者逻辑,并同时保证页面对用户的响应。

          简而言之,就是允许JavaScript创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。

          从而,可以用webWorker来处理一些比较耗时的计算。

          如下,主页面:

          <!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的内容:

          如何通过JS实现Web Worker高效并行处理?

          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),并将数据追加到div#result中。

          所以,执行上面的代码结果如下:

          图一

          待worker.js中的timedCount方法运算完后,执行postMessage操作,向主线程传数据,得图二。期间,并不影响主线程的运作。

          图二

          二、webWorker之常用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,此后无法再利用其进行消息传递。注意:一旦terminate后,无法重新启用,只能另外创建。

          //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

          当有消息发送时,触发该事件。且,消息发送是双向的,消息内容可通过data来获取。

          message使用,可见terminate中的demo

          4、error

          出错处理。且错误消息可以通过e.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); };

          执行上面代码结果:

          为什么会这样呢?原因是alert为window对象的方法,所以会报错undefined。

          worker.js执行的上下文,与主页面html执行时的上下文并不相同,最顶层的对象并不是window,woker.js执行的全局上下文,是个叫做WorkerGlobalScope的东东,所以无法访问window、与window相关的DOM API,但是可以与setTimeout、setInterval等协作。

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

          1、self

          我们可以使用 WorkerGlobalScope 的 self 属性来或者这个对象本身的引用

          2、location

          location 属性返回当线程被创建出来的时候与之关联的 WorkerLocation 对象,它表示用于初始化这个工作线程的脚步资源的绝对 URL,即使页面被多次重定向后,这个 URL 资源位置也不会改变。

          3、close

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

          4、importScripts

          我们可以通过importScripts()方法通过url在worker中加载库函数

          5、XMLHttpRequest

          有了它,才能发出Ajax请求

          6、setTimeout/setInterval以及addEventListener/postMessage

          四、关于worker

          我们可以做什么:

          1.可以加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信

          2.可以在worker中通过importScripts(url)加载另外的脚本文件

          3.可以使用setTimeout(), clearTimeout(), setInterval(), and clearInterval()

          4.可以使用XMLHttpRequest来发送请求

          5.可以访问navigator的部分属性

          局限性:

          1.不能跨域加载JS

          2.worker内代码不能访问DOM

          3.各个浏览器对Worker的实现不大一致,例如FF里允许worker中创建新的worker,而Chrome中就不行

          4.IE这个新特性

          以上就是浅谈webWorker的详细内容,更多关于浅谈webWorker的资料请关注自由互联其它相关文章!