ECharts实现动态曲线(中)遗留的问题是,切换标签页,浏览器里的定时器工作受到影响,甚至导致定时器停止工作而丢数据。而切回到原页签时,定时器又恢复正常。
这次使用Web Worker
解决这个问题,将浏览器端的定时器放到一个子线程里。
之前了解过,javascript是单线程,Web Worker
的存在也不能改变这一本质,因为Web Worker
受控于主线程
即javascript引擎线程,不能操作DOM。不过,Web Worker
可以使用XMLHttpRequest
,所以会用XMLHttpRequest
来实现Ajax
通信。
上手Web Worker
创建子线程
const worker = new Worker("./worker.js")
新建Worker对象
主线程与子线程间的通信
worker.postMessage(data)
主线程发送消息worker.onmessage = function(event){}
或者worker.addEventListener('message',function(){})
主线程接收消息(self|this).postMessage(data)
子线程发送消息(self|this).onmessage = function(event){}
或(self|this).addEventListener('message',function(){})
子线程接收消息
onmessage
只能添加一个消息处理程序,后来者居上,会发生覆盖;
addEventListener
能同时添加多个消息处理程序
关闭子线程
worker.terminate()
主线程关闭子线程self.close()
子线程关闭自身
实现
目录结构
浏览器端
- 新增了
worker.js
index.js
有变动MyChart.js
里删除getDataFromServer
index.html
里删除对jQuery CDN的引入
//index.js
var startBtn=null,endBtn = null;
initButtons();
const myChart = new MyChart(document.getElementById("myChart"));
myChart.init();
const worker = new Worker("./worker.js");
worker.onmessage = function(event){
const {type,datas} = event.data;
switch(type){
case "datas":myChart.update(datas);break;
case "closed":
startBtn.enable();
// worker.terminate();
break;
}
}
function startTimer(){
worker.postMessage({
type:"opening timer"
});
}
function closeTimer(timer){
worker.postMessage({
type:"closing timer"
});
}
function initButtons(){
startBtn = new MyButton(document.querySelector("#start"));
startBtn.addEventListener("click",function(){
startTimer();
startBtn.disable();
});
endBtn = new MyButton(document.querySelector("#end"));
endBtn.addEventListener("click",function(){
closeTimer();
});
}
//worker.js
var timer;
const worker = self;
worker.onmessage = function(event){
const {type} = event.data;
switch(type){
case "opening timer": openTimer();break;
case "closing timer":closeTimer();break;
}
}
function openTimer(){
timer = setInterval(getDataFromServer,250);
}
function closeTimer(){
clearInterval(timer);
worker.postMessage({
type:"closed"
});
//worker.close();
}
const createXHR = createXHRCreator();
function getDataFromServer(){
const xhr = createXHR();
xhr.open("GET","/getData");
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
worker.postMessage({
type:"datas",
datas:JSON.parse(xhr.response)
})
}
}
xhr.send();
}
function createXHRCreator(){
if(typeof XMLHttpRequest !== "undefined"){
return function createXHR(){
return new XMLHttpRequest();
}
}else if("ActiveXObject" in window){
return function createXHR(){
if(typeof arguments.callee.activeXString !== "string"){
var versions = [
"MSXML2.XMLHttp.6.0",
"MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"];
for(var i=0;i<versions.length;i++){
try{
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
}catch(e){
throw new Error(e);
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
}
}else{
return function createXHR(){
throw new Error("No XHR object supported");
}
}
}
服务器端
- 均无变动