欢迎来到DIVCSS5查找CSS资料与学习DIV CSS布局技术!
  一、明确 JavaScript 是单线程
 
  JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。
 
  听起来有些匪夷所思,为什么不设计成多线程提高效率呢?我们可以假设一种场景:
 
  假定  同时有两个线程,一个线程在某个  节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
 
  作为浏览器脚本语言,  的主要用途是与用户互动,以及操作  。
 
  这决定了它只能是单线程,否则会带来很复杂的同步问题。为了避免复杂性,从一诞生,  就是单线程,这已经成了这门语言的核心特征,估计短期内很难改变。
 
  二、新曙光:Web Worker
 
  单线程始终是一个痛点,为了利用多核  的计算能力,  提出  标准,允许  脚本创建多个线程。但是子线程完全受主线程控制,且不得操作  。
 
  所以,这个新标准并没有改变  单线程的本质。
 
  是现代浏览器提供的一个  多线程解决方案,我们可以找到很多使用场景:
 
  1.我们可以用  做一些大计算量的操作;
 
  2.可以实现轮询,改变某些状态;
 
  3.页头消息状态更新,比如页头的消息个数通知;
 
  4.高频用户交互,拼写检查,譬如:根据用户的输入习惯、历史记录以及缓存等信息来协助用户完成输入的纠错、校正功能等
 
  5.加密:加密有时候会非常地耗时,特别是如果当你需要经常加密很多数据的时候(比如,发往服务器前加密数据)。
 
  6.预取数据:为了优化网站或者网络应用及提升数据加载时间,你可以使用
 
  来提前加载部分数据以备不时之需。
 
  加密是一个使用  的绝佳场景,因为它并不需要访问  或者利用其它魔法,它只是纯粹使用算法进行计算而已。随着大众对个人敏感数据的日益重视,信息安全和加密也成为重中之重。这可以从近期的 12306 用户数据泄露事件中体现出来。
 
  一旦在 Worker 进行计算,它对于用户来说是无缝地且不会影响到用户体验。
 
  三、兼容性
 
  四、基本概念
 
  1.首先记得去判断是否支持
 
  2.创建一个新的  很简单
 
  postMessage() 方法和 onmessage 事件处理函数是 Workers 的黑魔法。
 
  3.  用来发送消息,而  用来监听消息
 
  在主线程中使用时,  和  必须挂在  对象上,而在  中使用时不用这样做。原因是,在  内部,  是有效的全局作用域。
 
  4.异常处理:
 
  5.终止
 
  线程会被立即杀死,不会有任何机会让它完成自己的操作或清理工作。
 
  6.在  线程中,  也可以调用自己的  方法进行关闭:
 
  五、快速开始
 
  为了快速掌握,我们来做一个小例子:项目结构如下
 
  Html
 
  main.js
 
  Work.js
 
  代码很简单,主线程发送:「写的真好!」
 
  web worker 收到消息,发现内容中含有「好」字,回传给主线程:「谢谢支持」
 
  六、局限性
 
  1.在  内,不能直接操作  节点,也不能使用  对象的默认方法和属性。然而我们可以使用大量  对象之下的东西,包括  ,  以及  专用的  等数据存储机制。
 
  这里举个例子,我们修改  :
 
  再来修改
 
  这时候运行就会报出:
 
  这是因为:  执行的上下文,与主页面  执行时的上下文并不相同,最顶层的对象并不是  ,  执行的全局上下文,而是  ,我们具体说明。
 
  2.  和主线程间的数据传递通过这样的消息机制进行:双方都使用  方法发送各自的消息,使用  事件处理函数来响应消息(消息被包含在  事件的  属性中)。
 
  这个过程中数据并不是被共享而是被复制。
 
  3.同源限制
 
  分配给  线程运行的脚本文件,必须与主线程的脚本文件同源。
 
  4.文件限制
 
  线程无法读取本地文件,即不能打开本机的文件系统  ,它所加载的脚本,必须来自服务器。
 
  5.不允许本地文件
 
  Uncaught SecurityError: Failed to create a worker:
 
  script at '(path)/worker.js'
 
  cannot be accessed from origin 'null'.
 
  Chrome doesn’t let you load web workers when running scripts from a local file.
 
  那如何解决呢?我们可以启动一个本地服务器,建议使用  ,简单易用。
 
  6.内容安全策略
 
  有别于创建它的  对象,  有它自己的执行上下文。因此普遍来说,  并不受限于创建它的  (或者父级  )的内容安全策略。
 
  我们来举个例子,假设一个  有如下头部声明:
 
  这个声明有一部分作用在于,禁止它内部包含的脚本代码使用  方法。然而,如果脚本代码创建了一个  ,在  上下文中执行的代码却是可以使用  的。
 
  为了给 worker 指定 CSP,必须为发送 worker 代码的请求本身加上一个 CSP。
 
  有一个例外情况,即  脚本的源如果是一个全局性的唯一的标识符(例如,它的  指定了数据模式或者  ),  则会继承创建它的  或者  的  。
 
  七、扩展:WorkerGlobalScope
 
  关于 ,我们可以在  上面找到文档:
 
  1.  :
 
  我们可以使用  的  属性来获取这个对象本身的引用。
 
  2.  :
 
  属性返回当线程被创建出来的时候与之关联的  对象,它表示用于初始化这个工作线程的脚步资源的绝对  ,即使页面被多次重定向后,这个  资源位置也不会改变。
 
  3.  :
 
  关闭当前线程,与  作用类似。
 
  4.  :
 
  当前上下文得  ,确保离线可用,同时可以自定义请求的响应。
 
  5.  :
 
  支持  语法。
 
  6.
 
  我们可以通过  方法通过  在  中加载库函数。
 
  7.
 
  有了它,才能发出  请求。
 
  8.可以使用:
 
  还有很多  可以使用,这里就不一一举例了。
 
  八、异常处理
 
  当  出现运行中错误时,它的  事件处理函数会被调用。它会收到一个扩展了  接口的名为  的事件。该事件不会冒泡并且可以被取消。
 
  为了防止触发默认动作,worker 可以调用错误事件的 preventDefault() 方法。

如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h62588.shtml