Worker对象处理线程代码分析
html代码
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<script type="text/javascript">
// 创建执行运算的线程
var worker = new Worker("kwb.js");
//接收从线程中传出的计算结果
worker.onmessage = function(event)
{
//消息文本放置在data属性中,可以是任何JavaScript对象.
alert("合计值为" + event.data + "。");
};
function kwb()
{
//获取文本框的值
var num1 = parseInt(document.getElementById("num1").value);
var num = parseInt(document.getElementById("num").value);
//对2个文本框提交的值进行判断
if(num<num1){
alert('提交的运算不符合要求');
return false;
}
//将获取的文本框的值用@拼接成字符串
var subs=num1+'@'+num;
//将数值传给线程
worker.postMessage(subs);
}
</script>
</head>
<body>
<h1>对给定2个数字之间所有数值的计算</h1>
<hr color="#FF0000"><br>
初始数值:<input type="text1" id="num1"><br><br>
终极数值:<input type="text" id="num"><br><br>
<button onclick="kwb()">计算</button>
</body>kwb.js代码:
onmessage = function(event){
var num = event.data;
var intarray=num.split('@'); //返回字符串中数字分隔符为@
var result = 0;
for (var i = parseInt(intarray[0]); i <= intarray[1]; i++) { //执行求和运算
result += i;
}
postMessage( result); //返回运算结果拼接成的字符串
}以下是对该 JavaScript 代码的逐行讲解:
onmessage = function(event){定义一个名为 onmessage 的函数,当接收到消息时会自动调用此函数。通常用于 Web Workers 中处理来自主线程的消息。event 参数包含了发送过来的数据。
var num = event.data;
从 event 对象中提取 data 属性,这个属性包含了从主线程传递过来的数据,并将其赋值给变量 num。
var intarray=num.split('@'); //返回字符串中数字分隔符为@将字符串 num 按照字符 '@' 进行分割,生成一个数组 intarray。例如,如果 num = "1@5",那么 intarray 就是 ["1", "5"]。注释说明了分隔符是 '@'。
var result = 0;
初始化一个变量 result 为 0,用于存储后续的求和结果。
for (var i = parseInt(intarray[0]); i <= intarray[1]; i++) { //执行求和运算使用 for 循环从 intarray[0](第一个数字)开始,到 intarray[1](第二个数字)结束,逐步累加每个数字。parseInt() 将字符串转换为整数。注释说明这是在执行求和运算。
result += i; }
在每次循环中,将当前数字 i 加到 result 上。循环结束后,result 包含了从第一个数到第二个数之间所有整数的总和。
postMessage( result); //返回运算结果拼接成的字符串
通过 postMessage() 方法将最终的求和结果 result 发送回主线程。注意,虽然注释提到“返回运算结果拼接成的字符串”,但实际代码中只是发送了一个数值,而不是字符串。
该代码整体功能是:接收一个以 '@' 分隔的两个数字组成的字符串,计算这两个数字之间的所有整数之和,并将结果返回给调用者。
postMessage() 方法将最终的求和结果 result 发送回主线程,
那是不是发送的结果就是sum,就是event.data?
postMessage() 方法发送的是 result 变量的值,而不是 event.data。
在代码中,event.data 是从主线程接收到的数据,通常是一个以 '@' 分隔的字符串,比如 "1@5"。
而 result 是代码内部计算得到的求和结果,是 result += i 累加后的数值。
所以 postMessage(result) 发送的是计算结果,而不是原始的 event.data。
简单来说:
event.data:接收的数据(如 "1@5")result:计算后的结果(如 15,即 1+2+3+4+5 的和)postMessage(result):发送的是计算结果,不是原始数据
那你看最后postMessage() 方法发送的
是 result 变量的值传到哪里去了?
传给谁了?
postMessage()方法发送的result变量值的传输流程如下:
发送方向:在Web Worker线程(kwb.js)中,
postMessage(result)将计算结果发送到主线程(即您的HTML页面)接收方:在HTML页面的主线程中,通过
worker.onmessage事件监听器来接收这个结果具体处理:接收到的数据存储在
event.data属性中,然后通过alert弹窗显示出来
所以完整的数据流向是:
Web Worker中的result变量 → postMessage()发送 → 主线程的worker.onmessage接收 → event.data → alert显示
这样就实现了从后台线程向前台页面传递计算结果的通信机制。
就是说最终计算的和存储到了event.data里面去了?
是的,最终计算的和确实存储到了event.data里面。
当Web Worker线程中的postMessage(result)执行时,计算结果result会被发送回主线程。在主线程中,通过worker.onmessage事件监听器接收这个消息时,计算结果就存储在event.data属性中。
这样设计使得主线程能够接收到Web Worker计算完成后的结果,并可以对其进行进一步处理或显示。
两段代码中的event是同一个吗?
这两段代码中的event参数虽然名称相同,但代表的含义和作用场景是不同的。
在第一段代码中,onmessage = function(event)是Web Worker线程中的事件处理函数。这里的event对象包含了从主线程发送过来的消息数据,event.data属性包含了实际传递的数据内容。当主线程调用worker.postMessage()发送数据时,Web Worker会接收到这个event对象。
在第二段代码中,worker.onmessage = function(event)是主线程中的事件处理函数。这里的event对象包含了从Web Worker线程发送回来的消息数据,event.data属性包含了Web Worker通过postMessage()发送的计算结果。
虽然两个event变量都包含data属性,但它们分别属于不同的执行环境:第一个属于Web Worker线程环境,第二个属于主线程环境。它们是两个独立的事件对象,只是都使用了相同的命名约定。
因此,这两个event对象虽然结构相似,但作用于不同的通信方向:第一个是接收主线程消息,第二个是接收Worker线程消息。
那这2个event能改成别的吗,
或者一个设为event1,另一个叫event2,行吗?
是的,这两个event参数可以改成不同的名称,比如event1和event2。这样可以更清楚地区分它们的作用。
在第一段代码中,Web Worker线程中的事件处理函数可以改为:
onmessage = function(event1){
var num = event1.data;
var intarray = num.split('@');
var result = 0;
for (var i = parseInt(intarray[0]); i <= intarray[1]; i++) {
result += i;
}
postMessage(result);
}在第二段代码中,主线程中的事件处理函数可以改为:
worker.onmessage = function(event2) {
alert("合计值为" + event2.data + "。");
};这样修改后,两个event参数的名称不同,便于理解它们分别属于不同的执行环境和作用域。
// Web Worker线程中的事件处理函数
onmessage = function(event1){
var num = event1.data;
var intarray = num.split('@');
var result = 0;
for (var i = parseInt(intarray[0]); i <= intarray[1]; i++) {
result += i;
}
postMessage(result);
}
// 主线程中的事件处理函数
worker.onmessage = function(event2) {
alert("合计值为" + event2.data + "。");
};代码说明:1. 该代码展示了如何将两个不同的event参数重命名为event1和event2
2. event1用于Web Worker线程接收主线程消息
3. event2用于主线程接收Web Worker线程返回的结果
如果改的话,函数块里面的也得对应改成和前面一样的,是吗
是的,如果将事件处理函数中的参数名从event改为其他名称,那么函数体内部所有使用该参数名的地方都必须相应修改。
例如,如果将第一个函数的参数名改为event1,那么函数体内所有使用event.data的地方都要改为event1.data。
// Web Worker线程中的事件处理函数
onmessage = function(event1){
var num = event1.data;
var intarray = num.split('@');
var result = 0;
for (var i = parseInt(intarray[0]); i <= intarray[1]; i++) {
result += i;
}
postMessage(result);
}
// 主线程中的事件处理函数
worker.onmessage = function(event2) {
alert("合计值为" + event2.data + "。");
};代码说明:1. 该示例展示了如何将事件处理函数的参数名从event修改为其他名称
2. 修改后需要确保函数体内所有相关引用都同步更新
3. 这样做可以提高代码可读性,明确区分不同环境中的事件对象
worker.postMessage(subs);
这一句代码,最终数值传给谁了?
上面代码中的 worker.postMessage(subs) 这一行代码,最终将数值传给了 Web Worker 线程。
具体来说,这行代码执行时:
创建了一个名为
worker的 Web Worker 对象(通过new Worker("kwb.js"))通过
worker.postMessage(subs)将拼接好的字符串subs发送给这个 Web Worker 线程这个字符串
subs包含了从 HTML 页面获取的两个数字,格式为 "数字1@数字2"Web Worker 线程中的
onmessage事件处理函数会接收到这个消息,然后进行计算处理
所以这个 postMessage 调用是将数据从主线程发送到 Web Worker 线程的通信机制。
那这一个先传还是计算好的和的值先传给线程?
数据传输和计算的顺序是:
首先:主线程中的
kwb()函数获取HTML页面中输入框的值然后:将这些值通过
worker.postMessage(subs)发送给Web Worker线程接着:Web Worker线程接收到数据后开始执行计算
最后:计算完成后,通过
postMessage(result)将结果传回主线程
所以是数据先传给线程,然后线程进行计算,计算完成后再将结果传回主线程。
这个过程体现了Web Worker异步处理的特点:主线程发送数据 → Worker线程处理计算 → Worker线程返回结果。