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){}
主線程接收消息self.postMessage(data)
或者this.postMessage(data)
子線程發送消息self.onmessage = function(event){}
或this.onmessage = function(event){}
子線程接收消息
關閉子線程
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");
}
}
}
服務器端
- 均無變動