js使用webWorker实现多线程
worker介绍:
- worker线程在浏览器后台运行,不干扰主线程。
- worker线程适用于计算高耗时的计算算法,以及轮询查询服务器状态的需求。
- worker线程的环境与主线程不同,不能获取DOM元素,无法使用
document
、window
以及parent
等对象,但可以使用navigator
与location
对象。 - worker线程中可以使用AJAX。
- 主线程与worker线程的通信是拷贝关系,传值非传址,所以worker线程对数据的任何改变都不会影响到主线程。
- 主线程与worker线程也可以传递二进制数据。
worker使用方法:
- 创建worker线程:
const worker = new Worker(’./js/worker/caculateVisibility.worker.js’);
- 向worker线程传入数据:
worker.postMessage(params)
- 监听worker线程的返回结果:
worker.onmessage = (evt) => {
console.log(evt.data);
}
- 主线程中关闭worker线程:
worker.terminate();
- worker线程中接收主线程发来的数据:
// self为worker线程的全局对象,类似于主线程的window对象
self.addEventListener(‘message’, (e) => {
console.log(e.data);
}
- worker线程中向主线程发送计算结果:
self.postMessage(result);
- worker线程关闭worker线程:
self.close();
- worker线程中加载外部文件:
// 需要注意的是,加载的外部文件的执行作用域依然是worker线程的作用域
// 可加载多个外部文件,用逗号分开即可
self.importScripts(’./caculate_visibility.js’);
- 主线程监听worker线程的错误:
worker.onerror(function (event) {
console.log([
'ERROR: Line ', e.lineno, ’ in ', e.filename, ‘: ‘, e.message
].join(’’));
});
原生js使用worker
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>Web Workers basic example</title>
</head>
<body>
<h1>Web<br>Workers<br>basic<br>example</h1>
<div class="controls" tabindex="0">
<form>
<div>
<label for="number1">Multiply number 1: </label>
<input type="text" id="number1" value="0">
</div>
<div>
<label for="number2">Multiply number 2: </label>
<input type="text" id="number2" value="0">
</div>
</form>
<p class="result">Result: 0</p>
</div>
<script src="main.js"></script>
</body>
</html>
main.js
const first = document.querySelector('#number1');
const second = document.querySelector('#number2');
const result = document.querySelector('.result');
if (window.Worker) {
const myWorker = new Worker("./worker.js");
first.onchange = function() {
myWorker.postMessage([first.value, second.value]);
console.log('Message posted to worker');
}
second.onchange = function() {
myWorker.postMessage([first.value, second.value]);
console.log('Message posted to worker');
}
myWorker.onmessage = function(e) {
result.textContent = e.data;
console.log('Message received from worker');
}
} else {
console.log('Your browser doesn\'t support web workers.');
}
worker.js
onmessage = function(e) {
importScripts('test.js')
console.log(test);
console.log('Worker: Message received from main script');
const result = e.data[0] * e.data[1];
if (isNaN(result)) {
postMessage('Please write two numbers');
} else {
const workerResult = 'Result: ' + result;
console.log('Worker: Posting message back to main script');
postMessage(workerResult);
}
}
test.js
function test() {
console.log(test);
}
Vue中使用Worker
方法一
使用vue-worker包
npm i vue-worker
//main.js
import VueWorker from 'vue-worker'
Vue.use(VueWorker);
// 组件中使用
this.$worker.run(_workerFn, [monitor, time, data])
.then(res => {
console.log('res', res);
})
function _workerFn(monitor, time, data) {
// importScripts('monitor.js');
// dosomething...
return 'success';
}
方法二
使用原生worker,需要配置vue
vue.config.js
module.exports = {
configureWebpack: config => {
config.module.rules.push({
test: /\.worker\.js$/,
use: {
loader: 'worker-loader',
options: { inline: true, name: 'workerName.[hash].js' }
}
})
},
}
caculate_visibility.js
const worker = new Worker('./js/worker/caculateVisibility.worker.js');//创建worker对象
const params = {
tle: {
line1: this.tle.line1,
line2: this.tle.line2
},
location: {
0: areaEntity.location[0],
1: areaEntity.location[1]
},
startTime: new Date(this.viewer.clock.startTime),
stopTime: new Date(this.viewer.clock.stopTime),
step: 40,
angle: rectSensorConfig.VerticalHalfAngle * 180 / Math.PI
};
worker.postMessage(params);// 向worker线程中传参
worker.onmessage = (evt) => { // 监听worker线程的反馈(计算好的结果会在这返回出来)
const coverage = evt.data.length / 1440;
const result = {
satellite: this,
timePoint: evt.data,
coverage: coverage
};
satelliteWithAreaVisibilityMap[this.entity.name].set(areaEntity.entity.name, result);
}
caculateVisibility.worker.js
self.addEventListener('message', (e) => { // worker线程中监听主线程的传参
self.importScripts('./caculate_visibility.js'); // worker线程中引入外部文件
const result = caculateVisibulity(e.data.tle, e.data.location, e.data.startTime, e.data.stopTime, e.data.step, e.data.angle); // 此方法是引入文件中定义的
self.postMessage(result); // 将计算结果返回给主线程
self.close(); // 关闭worker线程(因为worker很耗资源,用完需要及时关闭)
})