WebWorker是什么鬼?
时间:2023-03-15 18:29:51
科技观察
前言前端工程师一定有过这样的经历。当页面加载大量js文件时,用户界面可能会暂时“卡顿”。这个很好理解,因为js是单线程语言。说极端点,一段js里面有一个while(){}的死循环,然后点击页面的DOM元素,事件不会被触发,其实就是这些异步事件在排队,就等着页面的js渲染出来执行(从setTimeout说起JavaScript的运行机制),但是此时渲染已经进入了死循环,所以用户界面“卡住了”。在实际开发中,虽然不会出现类似的死循环,但是大量的js渲染还是会影响用户体验。这个时候我们就希望这个耗时的js***能够异步执行。setTimeout是个好方法,但是H5提供了更好的方法,WebWorker!WebWorker规范通过让Javascript在后台运行来解决这个问题。浏览器实现WebWorker规范的方式有很多种,使用线程,后台进程,或者运行在其他处理器核上的进程等等,具体的实现细节其实并不那么重要。重要的是,开发人员现在可以放心地运行Javascript,而不必担心影响用户体验。由于Worker属于H5家族,所以ie6一代可以走了。详细的浏览器兼容性可以参考https://img.ydisp.cn/news/20220731/xa4kw2b1bkc如果没有Worker,我们来看这样一段代码:
在页面上写创建一个div,然后监听它的点击事件,然后需要在js中计算斐波那契数列的第36项,并输出。这样的页面用户体验很差。如果斐波那契不执行,div的点击事件不能及时响应,递归求解斐波那契数列项相当耗时!这么耗时的js代码交给worker再合适不过了!WorkerWorker的使用方法非常简单。通过实例化Worker对象并传入要执行的Javascript文件的名称来创建一个新的WebWorker:varworker=newWorker('worker.js');此代码将导致浏览器下载worker.js,但只有Worker会收到它的消息以实际执行文件中的代码。要向Worker发送消息,您可以使用postMessage()方法。比如我想告诉Worker去求斐波那契数列的第36项:worker.postMessage(36);让我们看看Worker是如何接收消息的。当页面调用worker对象的postMessage()时,数据会异步传递给worker,进而触发worker中的message事件。要处理来自页面的数据,还要创建一个onmessage事件处理程序。(worker.js代码)self.onmessage=function(event){vardata=event.data;console.log(fibonacci(data));};functionfibonacci(n){return<2?n:arguments.callee(n-1)+arguments.callee(n-2);}页面可以向Worker传输数据,Worker也可以返回数据。通过消息事件监听页面:worker.onmessage=function(event){vardata=event.data;};工作人员通过消息和错误事件与页面进行通信。来自Workers的数据保存在event.data中。当Worker无法完成给定的任务时,会触发错误事件。具体来说,只要Worker内部的Javascript在执行过程中遇到错误,就会触发error事件。当错误事件发生时,事件对象包含三个属性:filename、lineno、message,分别代表错误的文件名、代码行号和完整的错误信息:worker.onerror=function(event){console.log(event.filename,event.lineno,event.message);};我们建议大家在使用worker的时候总是写error事件,就像在使用ajax的时候,总是写获取失败时的补救操作。完整代码:html文件:
worker.js文件:self.onmessage=function(event){vardata=event.data;varans=fibonacci(data);this.postMessage(ans);};functionfibonacci(n){return<2?n:arguments.callee(n-1)+arguments.callee(n-2);}简单总结:WEB主线程:通过varworker=newWorker(url)加载一个js文件创建一个worker,并返回一个worker实例。通过worker.postMessage(data)方法向worker发送数据。绑定worker.onmessage方法接收worker发送的数据。您可以使用worker.terminate()来终止worker的执行。worker新建线程:绑定onmessage方法接收主线程发送过来的数据。通过postMessage(data)方法向主线程发送数据。您可以使用self.close()来终止worker的执行。Worker关于WebWorkers的其他事情最重要的是它执行的Javascript代码完全在另一个范围内,并且不与当前网页中的代码共享范围。在WebWorker中,还有一个全局对象(worker对象本身,this和self指的是worker对象本身)等对象和方法。WebWorker中的代码无法访问DOM。那么Worker中的代码可以访问哪些对象和方法呢?最小化导航器对象,包括onLine、appName、appVersion、userAgent和平台属性只读位置对象setTimeout()、setInterval()、clearTimeout()、clearInterval()方法XMLHttpRequest构造函数可以随时终止Worker。在worker.js中,我们可以使用self.close()方法,而在页面中,我们可以使用worker.terminal()方法,这样就不会触发error和message事件。