• 售前

  • 售后

热门帖子
入门百科

突袭HTML5之Javascript API扩展1—Web Worker异步实行及干系概述

[复制链接]
DJ牧南 显示全部楼层 发表于 2021-10-25 19:50:48 |阅读模式 打印 上一主题 下一主题
Javascript实行机制
在HTML5之前,欣赏器中JavaScript的运行都是以单线程的方式工作的,固然有多种方式实现了对多线程的模拟(比方:Javascript 中的 setinterval 方法,setTimeout 方法等),但是在本质上步伐的运行仍旧是由 JavaScript 引擎以单线程调理的方式进行的。在 HTML5 中引入的工作线程使得欣赏器端的 Javascript 引擎可以并发地实行 Javascript 代码,从而实现了对欣赏器端多线程编程的精良支持。

Javascript中的多线程 - WebWorker
HTML5 中的 Web Worker 可以分为两种不同线程范例,一个是专用线程 Dedicated Worker,一个是共享线程 Shared Worker。两种范例的线程各有不同的用途。
专用型web worker
专用型worker与创建它的脚本毗连在一起,它可以与其他的worker或是欣赏器组件通讯,但是他不能与DOM通讯。专用的寄义,我想就是这个线程一次只处理一个需求。专用线程在除了IE外的各种主流欣赏器中都实现了,可以放心利用。
创建线程
创建worker很简单,只要把须要在线程中实行的JavaScript文件的文件名传给构造函数就可以了。
线程通讯
在主线程与子线程间进行通讯,利用的是线程对象的postMessage和onmessage方法。不管是谁向谁发数据,发送发利用的都是postMessage方法,接收方都是利用onmessage方法接收数据。postMessage只有一个参数,那就是传递的数据,onmessage也只有一个参数,假设为event,则通过event.data获取收到的数据。
发送JSON数据
JSON是JS原生支持的东西,不消白不消,复杂的数据就用JSON传送吧。比方:

复制代码代码如下:
postMessage({'cmd': 'init', 'timestamp': Date.now()});

处理错误
当线程发生错误的时间,它的onerror事故回调会被调用。以是处理错误的方式很简单,就是挂接线程实例的onerror事故。这个回调函数有一个参数error,这个参数有3个字段:message - 错误消息;filename - 发生错误的脚本文件;lineno - 发生错误的行。
销毁线程
在线程内部,利用close方法线程自己销毁自己。在线程外部的主线程中,利用线程实例的terminate方法销毁线程。
下面从一个例子看线程的根本利用:
HTML代码:

复制代码代码如下:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>web worker fibonacci</title>
<script type="text/javascript">
onload = function(){
var worker = new Worker('fibonacci.js');
worker.onmessage = function(event) {
console.log("Result:" + event.data);
};
worker.onerror = function(error) {
console.log("Error:" + error.message);
};
worker.postMessage(40);
}
</script>
</head>
<body>
</body>
</html>

脚本文件fibonacci.js代码:

复制代码代码如下:
//fibonacci.js
var fibonacci = function(n) {
return n < 2 ? n : arguments.callee(n - 1) + arguments.callee(n - 2);
};
onmessage = function(event) {
var n = parseInt(event.data, 10);
postMessage(fibonacci(n));
};

把它们放到雷同的目录,运行页面文件,查看控制台,可以看到运行的结果。
这里还有一点,在主线程中,onmessage事故可以利用另外一种方式挂接:

复制代码代码如下:
worker.addEventListener('message', function(event) {
console.log("Result:" + event.data);
}, false);

个人以为很贫困,不如用onmessage直接。
利用其他脚本文件
工作线程可以利用全局方法importScripts来加载和利用其他的域内脚本文件大概类库。比方下面都是正当的利用方式:

复制代码代码如下:
importScripts();/* imports nothing */
importScripts('foo.js'); /* imports just "foo.js" */
importScripts('foo.js', 'bar.js');/* imports two scripts */

导入以后,可以直接利用这些文件中的方法。看一个网上的小例子:

复制代码代码如下:
/**
* 利用 importScripts 方法引入外部资源脚本,在这里我们利用了数学公式盘算工具库 math_utilities.js
* 当 JavaScript 引擎对这个资源文件加载完毕后,继续实行下面的代码。同时,下面的的代码可以访问和调用
* 在资源文件中定义的变量和方法。
**/
importScripts('math_utilities.js');
onmessage = function (event)
{
var first = event.data.first;
var second = event.data.second;
calculate(first,second);
};
function calculate(first,second) {
//do the calculation work
var common_divisor=divisor(first,second);
var common_multiple=multiple(first,second);
postMessage("Work done! " +
"The least common multiple is " + common_divisor +
" and the greatest common divisor is "+common_multiple);
}

网上也有网友想到了利用这里的importScripts方法解决资源预加载的题目(欣赏器预先加载资源,而不会对资源进行分析和实行),原理也很简单。
线程嵌套
在工作线程中还可以在创建子线程,各种利用照旧一样的。
同步题目
Worker没有锁的机制,多线程的同步题目只能靠代码来解决(好比定义信号变量)。
共享型SharedWebWorker
共享型web worker主要实用于多毗连并发的题目。由于要处理多毗连,以是它的API与专用型worker稍微有点区别。除了这一点,共享型web worker和专用型worker一样,不能访问DOM,而且对窗体属性的访问也受到限定。共享型web worker也不能凌驾通讯。
页面脚本可以与共享型web worker通讯,然而,与专用型web worker(利用了一个隐式的端口通讯)稍微有点不同的是,通讯是显式的通过利用一个端口(port)对象并附加上一个消息事故处理步伐来进行的。
在收到web worker脚本的首个消息之后,共享型web worker把一个事故处理步伐附加到激活的端口上。一般环境下,处理步伐会运行自己的postMessage()方法来把一个消息返回给调用代码,接着端口的start()方法生成一个有效的消息进程。
看网上能找到的的唯一个例子:创建一个共享线程用于接收从不同毗连发送过来的指令,然后实现自己的指令处理逻辑,指令处理完成后将结果返回到各个不同的毗连用户。
HTML代码:

复制代码代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Shared worker example: how to use shared worker in HTML5</title>
<script>
var worker = new SharedWorker('sharedworker.js');
var log = document.getElementById('response_from_worker');
worker.port.addEventListener('message', function(e) {
//log the response data in web page
log.textContent =e.data;
}, false);
worker.port.start();
worker.port.postMessage('ping from user web page..');
//following method will send user input to sharedworker
function postMessageToSharedWorker(input)
{
//define a json object to construct the request
var instructions={instruction:input.value};
worker.port.postMessage(instructions);
}
</script>
</head>
<body onload=''>
<output id='response_from_worker'>
Shared worker example: how to use shared worker in HTML5
</output>
send instructions to shared worker:
<input type="text" autofocus oninput="postMessageToSharedWorker(this);return false;">
</input>
</body>
</html>

脚本文件代码:

复制代码代码如下:
// 创建一个共享线程用于接收从不同毗连发送过来的指令,指令处理完成后将结果返回到各个不同的毗连用户。
var connect_number = 0;
onconnect = function(e) {
connect_number =connect_number+ 1;
//get the first port here
var port = e.ports[0];
port.postMessage('A new connection! The current connection number is '
+ connect_number);
port.onmessage = function(e) {
//get instructions from requester
var instruction=e.data.instruction;
var results=execute_instruction(instruction);
port.postMessage('Request: '+instruction+' Response '+results
+' from shared worker...');
};
};
/*
* this function will be used to execute the instructions send from requester
* @param instruction
* @return
*/
function execute_instruction(instruction)
{
var result_value;
//implement your logic here
//execute the instruction...
return result_value;
}

在上面的共享线程例子中,在主页面即各个用户毗连页面构造出一个共享线程对象,然后定义了一个方法 postMessageToSharedWorker 向共享线程发送来之用户的指令。同时,在共享线程的实现代码片段中定义 connect_number 用来记录毗连到这个共享线程的总数。之后,用 onconnect 事故处理器担当来自不同用户的毗连,分析它们传递过来的指令。最后,定义一个了方法 execute_instruction 用于实行用户的指令,指令实行完成后将结果返回给各个用户。

这里我们并没有跟前面的例子一样利用到了工作线程的 onmessage 事故处理器,而是利用了另外一种方式 addEventListener。实际上,前面已经说过,这两种的实现原理根本同等,只是在这里有些稍微的差异,假如利用到了 addEventListener 来担当来自共享线程的消息,那么就要先利用 worker.port.start() 方法来启动这个端口。之后就可以像工作线程的利用方式一样正常的接收和发送消息。
最后陈诉
线程中能做的事
1.能利用setTimeout(), clearTimeout(), setInterval(),clearInterval()等函数。
2.能利用navigator对象。
3.能利用XMLHttpRequest来发送请求。
4.可以在线程中利用Web Storage。
5.线程中可以用self获取本线程的作用域。
线程中不能做的事
1.线程中是不能利用除navigator外的DOM/BOM对象,比方window,document(想要利用的话只能发送消息给worker创建者,通过回调函数利用)。
2.线程中不能利用主线程中的变量和函数。
3.线程中不能利用有"挂起"效果的利用下令,比方alert等。
4.线程中不能跨域加载JS。
线程也是须要斲丧资源的,而且利用线程也会带来肯定的复杂性,以是假如没有富足的来由来利用额外的线程的话,那么就不要用它。
实用参考
官方文档:http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html
WebWorker分类阐明:http://www.w3schools.com/html5/html5_webworkers.asp
脚本之家:https://www.jb51.net/w3school/html5/
WebWorker概述:https://developer.mozilla.org/en/Using_web_workers

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作