当前位置: 首页 > news >正文

html5 Web Workers.RP

虽然在JavaScript中有setInterval和setTimeout函数使javaScript看起来好像使多线程执行,单实际上JavaScript使单线程的,一次只能做一件事情(关于JavaScript单线程可以看看setTimeout()和setInterval() 何时被调用执行),看个简单的例子证明一下

复制代码
<!DOCTYPE html>
<html> <head> <title>Web Workers</title> </head> <body> <h1>Web Workers</h1> <script type="text/javascript"> setTimeout(function(){ console.log('timeout function'); },1000); alert('do not close'); </script> </body> </html>
复制代码

 

页面一运行就会弹出一个对话框,如果setTimeout是在另外一个线程运行,那么过一秒钟控制台就会打印“timeout function”,事实是只要不关闭对话框,控制台永远不会输出文字,这两句话确实是在一个线程内运行的。

这样的设计使JavaScript比较简单,但有时候也很令人烦恼,因为单线程的设计意味着JavaScript代码必须很快运行完,常见的问题就是一段复杂的JavaScript脚本会中断页面其它脚本执行,甚至会出现页面失去响应,这也就是为什么ajax的API要设计成异步的。

Web Workers

在html5规范中引入了web workers概念,解决客户端JavaScript无法多线程的问题,其定义的worker是指代码的并行线程,不过web worker处于一个自包含的环境中,无法访问主线程的window对象和document对象,和主线程通信只能通过异步消息传递机制。(《JavaScript权威指南》)

web worker

我们需要把希望单独执行的javascript代码放到一个单独的js文件中,然后在页面中调用Worker构造函数来创建一个线程,参数是该文件路径,参数存放如果是相对地址,那么要以包含调用Worker构造函数语句所在脚本为参照,如果是绝对路径,需要保证同源(协议+主机+端口)。这个文件不需要我们在页面使用script标签显示引用

var worker=new Worker('js/worker.js');

 

这时候这个文件就会被异步加载并在后台执行,创建成功地worker是酱紫的

我们可以看到worker对象只有两个属性,其实是两个回调函数句柄

  1. onerror:当worker运行出现错误,并且没有在worker中ing捕获,会在此捕获
  2. onmessage:当worker向主线程发送消息是调用

在其prototype内有两个重要方法

  1. postMessage:很熟悉的赶脚,之前我们介绍过window对象的postMessage()方法,woker的postMessage方法和window的比较类似,但参数略有不同,只需要传递消息内容就可以,而且支持所有JavaScript原生数据类型,当然不放心的话同样也可以序列化为字符串传递
  2. terminate:终止worker执行,有些worker执行比较慢,主线程可以主动终止其执行

简单的小例子

在一个页面显示0~10000内所有可以被n整除的数,当然我们不用i*n这种,要略微使计算显得复杂一些嘛

index.html

复制代码
 1 <!DOCTYPE html>
 2 <html>  3 <head>  4 <title>Web Workers</title>  5 </head>  6 <body>  7 <h1>Web Workers</h1>  8  9 <div id="test" style="width:500px;"></div> 10 <script type="text/javascript"> 11 var worker=new Worker('js/worker.js'); 12  worker.postMessage({ 13  n:69 14  }); 15 16  worker.onmessage=function(e){ 17 var test=document.getElementById('test').innerHTML=e.data; 18  }; 19 </script> 20 </body> 21 </html>
复制代码

 

/js/worker.js

复制代码
function calc(n){
    var result=[];
    for(var i=1;i<10000;i++){
        var tem=i;
        if(i%n==0){ if(i%(10*n)==0){ tem+='<br/>'; } result.push(tem); } } self.postMessage(result.join(' ')); self.close(); } onmessage=function(e){ calc(e.data.n); };
复制代码

 

 好像有几点没提到

worker.onmessage

绑定主线程的message事件,当worker调用postMessage时方法时,绑定的事件处理程序会被调用到,传递来的数据可以使用MouseEvent的data属性获取,通过target属性还可以获取worker对象

self是什么

self是woker中对自身的引用,有些像this

close()

在worker内部调用close()方法效果和在外部调用worker实例的terminate()方法效果一样,终止worker运行

onmessage

在这个句柄内接收外部调用者传递的参数,参数可以通过e.data获取

self.postMessage()

没错通过这个方法我们可以在worker内把结果传递给主线程,主线程上绑定的message事件的处理程序会被调用

worker的作用域

web worker的简单用法就是这样,但有些姿势还是得了解一下。

全新的JavaScript环境

当一个Worker实例被创建的时候,它会在一个全新的JavaScript运行环境中,完全和创建worker的脚本分离开,即使我们传递的消息是引用类型它们也是复制传递的,修改worker中的参数不影响创建脚本中的参数。

importScripts()

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

importScripts('utility/dialog.js','common/cookie.js');

 

方法可以接受多个url,相对地址的url以当前worker为参照,方法会按照参数顺序依次下载运行库函数,如果中间某个脚本出错,剩下的都不会被载入和执行,而且这个方法是同步的,只有所有脚本都加载、运行完后才会返回。

worker执行模型

worker线程从上到下同步运行它的代码,然后进入异步阶段来对事件及计时器响应,如果worker注册了message事件处理程序,只要其有可能触发,worker就一直在内存中,不会退出,但如果worker没有监听消息,那么当所有任务执行完毕(包括计数器)后,他就会退出。

web worker中可以使用什么

 前面提到在worker中不能使用window对象和docuemnt对象,那么能够使用什么呢

  • JavaScript的全局对象:JSON、Date()、Array
  • self自身引用
  • location对象,但是其属性都是只读的,改了也影响不到调用者
  • navigator对象
  • setTimeout()、setInterval()及其对应清除方法
  • addEventListener()、removeEventListener()

最后

web worker还支持sub worker和共享worker,这方面没有太仔细看,浏览器兼容性也不讨理想,有兴趣同学可以上网搜索研究一下。

 

文转:http://www.cnblogs.com/dolphinX/p/3452684.html

转载于:https://www.cnblogs.com/Leroscox/p/6985157.html

相关文章:

  • TensorFlow 生成 .ckpt 和 .pb
  • salesforce 简单的PDF报价单打印
  • 1.8 Oracle 登陆时报错信息:无监听程序 我的程序猿之路:第八章
  • [BZOJ 2142]礼物(扩展Lucas定理)
  • iOS UISlider的使用
  • CSS 各种形状
  • 用php 生成 excel 表格
  • .Net 路由处理厉害了
  • mybatis中批量插入以及更新
  • robots.txt的语法和写法详解
  • STL 标准模板库
  • Servlet 详解
  • I/O流
  • 菜鸟学习Redis(二)——Redis集群
  • 行为模式--代理Proxy模式(Java)
  • 时间复杂度分析经典问题——最大子序列和
  • 【React系列】如何构建React应用程序
  • 10个最佳ES6特性 ES7与ES8的特性
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • CSS魔法堂:Absolute Positioning就这个样
  • Javascript弹出层-初探
  • log4j2输出到kafka
  • Python_网络编程
  • spring + angular 实现导出excel
  • Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比...
  • ucore操作系统实验笔记 - 重新理解中断
  • WebSocket使用
  • windows下mongoDB的环境配置
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 将回调地狱按在地上摩擦的Promise
  • 精彩代码 vue.js
  • 警报:线上事故之CountDownLatch的威力
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • python最赚钱的4个方向,你最心动的是哪个?
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • $.ajax()方法详解
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (6)设计一个TimeMap
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • .Net CF下精确的计时器
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • .NET/C# 的字符串暂存池
  • ??如何把JavaScript脚本中的参数传到java代码段中
  • @ModelAttribute 注解
  • @Transactional类内部访问失效原因详解
  • [ CTF ] WriteUp-2022年春秋杯网络安全联赛-冬季赛
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [1204 寻找子串位置] 解题报告