JavaScript多线程,网页多线程
HTML5总是被谈论。太多的功能和有趣的API让人耳目一新。但是很多童鞋还停留在语义阶段,忽略了HTML5的强大。
在这一节中,我们来讨论多线程网络工作者。
一、明确 JavaScript 是单线程
JavaScript的一个特点就是单线程,也就是一次只能做一件事。
听起来很奇怪,为什么不设计多线程来提高效率?我们可以假设一个场景:
假设JavaScript同时有两个线程,一个线程向DOM节点添加内容,另一个线程删除节点。浏览器应该以哪个线程为标准?
JavaScript作为一种浏览器脚本语言,主要用于与用户交互和操作DOM。
这就决定了它只能单线程,否则会带来复杂的同步问题。为了避免复杂,JavaScript从诞生之日起就是单线程的,这也成为了这种语言的核心特征。估计短期内很难改变。
二、新曙光:Web Worker
单线程始终是一个痛点。为了利用多核CPU的计算能力,HTML5提出了Web Worker标准,允许JavaScript脚本创建多线程。但是子线程完全由主线程控制,不能操作DOM。
所以这个新标准并没有改变JavaScript单线程的本质。
Web Workers是现代浏览器提供的JavaScript多线程解决方案,我们可以找到很多使用场景:
1.我们可以用Web Worker做一些计算量大的操作;
2.可以实现轮询来改变一些状态;
3.更新报头的消息状态,例如报头中消息数量的通知;
4.高频的用户交互,比如拼写检查,根据用户的输入习惯、历史记录、缓存等信息,帮助用户完成输入纠错和修正功能。
5.加密:加密有时非常耗时,尤其是当您需要频繁加密大量数据时(例如,在将数据发送到服务器之前加密数据)。
6.预取数据:为了优化网站或网络应用,提高数据加载时间,可以使用Workers。
以备不时之需。
加密是使用Web Worker的绝佳场景,因为它不需要访问DOM或使用其他魔法,它只是使用算法进行计算。随着公众对个人敏感数据的日益重视,信息安全和加密成为重中之重。这在最近的12306用户数据泄露事件中就可以体现出来。
一旦在Worker中进行计算,对用户来说就是无缝的,不会影响用户体验。
三、兼容性
四、基本概念
1.首先记得判断是否支持。
如果(窗口。工人){.}2.创建一个新的工人非常简单
const my Worker=new Worker( Worker . js );postMessage()方法和onmessage事件处理程序是Workers的黑魔法。
3.postMessage用于发送消息,onmessage用于监控消息。
const Worker=new Worker( src/Worker . js );worker . on message=e={ console . log(e . data);};Worker.postMessage(你好!);在主线程中使用时,onmessage和postMessage()必须挂在worker对象上,而不是挂在worker中。原因是在worker内部,worker是一个有效的全局范围。
4.异常处理:
worker . on error=function(error){ console . log(error . message);投掷误差;};5.解雇工人
worker . termin ate();工作线程将立即被终止,并且它将没有机会完成自己的操作或清理。
6.在worker线程中,worker也可以调用自己的close方法来关闭:
close();五、快速开始
为了快速掌握,我们举个小例子:项目结构如下
index.htmlsrcmain . jsworker . jshtml
html head title web Work Demo/title meta charset= UTF-8 //head body div id= app Hello Jartto!/div script src= src/main . js /script/body/html main . js
const Worker=new Worker( src/Worker . js );worker . on message=e={ const message=e . data;console . log(`[来自Worker]:$ { message } `);document.getElementById(app )。innerHTML=message};Worker.postMessage(写得真好!);Work.js
on message=e={ const message=e . data;console . log(`[From Main]:$ { message } `);if(message . index of( good )-1){ postMessage(谢谢支持);}};代码非常简单。主线程发:“写得好!」
web worker收到消息,发现内容包含“好”字,发回主线程:“谢谢支持”
六、局限性
1.在worker内部,不能直接操作DOM节点,也不能使用window对象的默认方法和属性。但是我们可以在window对象下使用大量的东西,包括WebSockets,IndexedDB,以及FireFox OS专用的Data Store API等数据存储机制。
这里有一个例子,我们修改main.js:
const Worker=new Worker( src/Worker . js );worker . on message=e={ const message=e . data;console . log(`[来自Worker]:$ { message } `);document.getElementById(app )。innerHTML=message};worker . on error=function(error){ console . log(error);worker . termin ate();};Worker.postMessage(写得真好!);然后修改work.js
alert( jar tto );on message=e={ const message=e . data;console . log(`[From Main]:$ { message } `);if(message . index of( good )-1){ postMessage(谢谢支持);}};此时,操作将报告:
这是因为:worker.js执行的上下文和主页面HTML执行的上下文不一样。最顶层的对象不是执行Window和woker.js的全局上下文,而是WorkerGlobalScope,我们会详细解释。
2.workers与主线程之间的数据传输是通过这样一种消息机制来进行的:双方使用postMessage()方法发送各自的消息,使用onmessage事件处理函数响应消息(消息包含在消息事件的data属性中)。
在这个过程中,数据不是共享的,而是复制的。
3.同源限制
分配给工作线程的脚本文件必须与主线程的脚本文件相同。
4.文件限制
工作线程无法读取本地文件,也就是无法打开本地文件系统(file://),加载的脚本必须来自服务器。
5.不允许本地文件。
未捕获的SecurityError:无法创建工作进程:
在(path)/worker.js 处编写脚本
无法从原点“null”访问。
Chrome不允许你从本地文件运行脚本时加载web workers。
那怎么解决呢?我们可以启动一个本地服务器。推荐使用http-server,比较好用。
6.内容安全政策
与创建它的文档对象不同,worker有自己的执行上下文。因此,一般来说,工作者不受创建它的文档(或父工作者)的内容安全策略的限制。
我们举个例子。假设一个文档有以下头声明:
content-security-policy:script-src self 该语句部分用于禁止其中包含的脚本代码使用eval()方法。但是,如果脚本代码创建了一个worker,那么在worker上下文中执行的代码可以使用eval()。
为了将CSP分配给工作者,必须将CSP添加到发送工作者代码本身的请求中。
有一个例外,即如果工作脚本的源是一个全局唯一标识符(例如,它的URL指定一个数据模式或blob),则该工作脚本将继承创建它的工作脚本的文档或CSP。
七、扩展:WorkerGlobalScope
关于,我们可以在MDN上找到文档:
1.自我:
我们可以使用WorkerGlobalScope的self属性来获取这个对象本身的引用。
2.位置:
location属性返回创建线程时与线程相关联的WorkerLocation对象,它代表用于初始化该工作线程的足迹资源的绝对URL。即使页面被多次重定向,这个URL资源的位置也不会改变。
3.关闭:
关闭当前线程,类似于terminate。
4.缓存:
当前上下文的CacheStorage确保脱机可用性,并且可以定制请求的响应。
5.控制台:
支持控制台语法。
6.导入脚本
我们可以通过importScripts()方法在worker中通过url加载库函数。
7.XMLHttpRequest
有了它,您可以发出Ajax请求。
8.您可以使用:
SetTimeout/SetInterval AddEvent Listener/Postmessage有很多API可以用,这里就不举例了。
八、异常处理
当一个worker出现运行错误时,它的onerror事件处理程序将被调用。它将接收一个名为error的事件,该事件扩展了ErrorEvent接口。活动不会冒泡,可以取消。
为了防止触发默认操作,工作线程可以调用错误事件的preventDefault()方法。
错误我们常用以下三个关键信息:
Message:可读的错误消息;Filename:发生错误的脚本文件的名称;Lineno:发生错误的脚本文件的行号;worker . on error=function(error){ console . log(error . message);投掷误差;};这就是本文的全部内容。希望对大家的学习和支持有帮助。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。