当前位置: 首页 > Web前端 > HTML5

了解一下前端的webWorkerer

时间:2023-04-05 13:56:29 HTML5

我们都知道JavaScript是单线程的,一次只能处理一个任务。我们将通过setTimeout()、setInterval()、ajax和事件处理程序等技术来模拟“并行”。”。但这两者都不是真正意义上的并行:WebWorkers是HTML5标准的一部分,它定义了一个API,允许JavaScript程序在主线程之外的另一个线程中运行。这在很大程度上利用了不断增长的计算能力今天的计算机:同时并行处理两个任务的能力。学习游泳和健身:博客,前端积累的文档,公众号,GitHub场景。当我们有一些任务需要花费大量时间和执行复杂的计算,页面会卡顿:用户点击页面需要很长时间才能响应,因为前面的任务还没有完成,后面的任务只能排队等待。对于用户来说,这样的体验是无疑是不好的,而webworkers的诞生就是为了解决这种复杂的计算,需要花费大量的时间!WebWorker的作用:创建一个工作线程WebWorker允许在主线程之外创建一个工作线程。工作线程也可以在后台执行自己的任务,互不干扰。这使得JS成为多线程环境。我们可以将高延迟和耗时的操作分配给工作线程,最后将结果返回给主线程。假设,主线程会很流畅!先来看看主线程:codepen,这里我写了一个类,里面有详细的注释,大家可以参考一下。创建一个worker对象:主线程调用newWorker()构造函数创建一个新的worker线程。构造函数的参数是一个url。这个url有两种??生成方式:脚本文件:constworker=newWorker('https://~.js');因为worker的两个限制:分配给worker线程运行的脚本文件必须是与主线程的脚本文件同源。worker无法读取本地文件(无法打开本地文件系统file://),它加载的脚本必须来自网络。可见限制还是很多的。如果要使用这种形式,建议将文件放在项目中的static文件夹中,打包时直接复制,这样我们就可以获得固定链接。StringForm:constdata=`//workerthreaddosomething`;//converttobinaryobjectconstblob=newBlob([data]);//generateurlconsturl=window.URL.createObjectURL(blob);//加载urlconstworker=newWorker(url);栗子中使用了这种形式,方便我们演示。项目中:我们可以把工作线程的逻辑写在js文件中,然后字符串化,然后导出导入,配合webpack进行模块化管理,使用方便。主线程其他API:1.主线程与工作线程通信:worker.postMessage({hello:['hello','world']});它们之间的通信可以传递对象和数组,因此我们可以根据彼此之间传递的信息进行一些操作。比如可以设置一个type属性,值为hello时执行哪个函数,值为world时执行什么函数。值得注意的是,它们之间的通信是以副本的形式传输数据,传输的对象需要先序列化,然后在另一端反序列化。这意味着:我们不能传递无法序列化的数据,例如函数,并且会抛出错误。更改一端的数据不会影响另一端,因为没有对数据的引用并且它被复制了。2、监听工作线程返回的信息worker.onmessage=function(e){console.log('父进程收到的数据:',e.data);//doSomething();}3.主线程关闭工作线程Worker线程创建成功后会一直运行,有利于随时响应主线程的通信。这也是为什么Worker会消耗更多计算机的计算资源(CPU)的原因。一旦用完,工作线程就应该关闭。工人.终止();//主线程关闭工作线程4.监听错误//工作线程报错worker.onerror=e=>{//e.filename-发生错误的脚本文件名;e.lineno——错误发生的行号;和e.message-可读的错误消息console.log('onerror',e);};也可以像我给的栗子一样把两个error写在一起,有errors把信息拿出来就行了。工作线程self代表工作进程本身。工作线程的执行上下文是一个叫做WorkerGlobalScope的东西,它不同于主线程的上下文(窗口)。我们可以使用self/WorkerGlobalScope来访问全局对象。监听来自主线程的消息:self.onmessage=e=>{console.log('Messagefromthemainthread:',e.data);//做一点事};向主线程发送消息self.postMessage({hello:['Thisinformation','fromworkerthread']});工作线程自行关闭self.close()工作线程加载脚本:工作线程可以访问一个全局函数imrtScripts()来导入脚本,该函数接受0个或多个URI作为参数。importScripts('http~.js','http~2.js');脚本中的全局变量可以被工作线程使用。下载脚本的顺序不固定,但它们将按照传递给importScripts()的文件名的顺序执行。这个过程是同步的。Worker线程限制因为worker创建了另外一个线程,这个线程不在主线程上,所以会有相应的一些限制。我们不能使用以下对象:window对象document对象DOM对象parent对象我们可以使用以下对象/函数:browser:navigator对象URL:location对象,只读Sendrequest:XMLHttpRequest对象Timer:setTimeout/setInterval,worker中轮询线程也很棒!应用缓存:ApplicationCacheMultipleworkerthreads可以在主线程中创建多个工作线程。栗子在底部。您也可以在工作线程中创建一个新的工作线程,使用相同的源脚本文件来创建。如果在工作线程中新建工作线程,则不能使用window.URL.createObjectURL(blob)。您需要使用相同的源脚本文件来创建一个新的工作线程,因为我们无法访问窗口对象。这里不方便演示。在主线程中创建工作线程是套路,但是改为以脚本文件的形式创建工作线程。线程间传递二进制数据因为主线程和工作线程之间的通信是拷贝关系,所以当我们要将一个巨大的二进制文件传递给工作线程处理时(工作线程就是用来干这个的),那么使用copy方法要传输数据,无疑会造成性能问题。幸运的是,WebWorker提供了一种传输数据的方式,可以让主线程直接将二进制数据传输给子线程。这种方法比原来的复制方法有巨大的性能提升。一旦数据转移到其他线程,原来的线程就不能再使用二进制数据了。这是为了防止出现多个线程同时修改数据的麻烦情况。(1024*1024*32);//32MBfor(vari=0;i