當(dāng)瀏覽器切換到后臺運(yùn)行,操作系統(tǒng)會把瀏覽器掛起,掛起之后,比如定時器,在回到原來頁面的時候,會出現(xiàn)獲取秒有重復(fù)的問題,代碼參考如下
var timer = setInterval(function() {
var date1 = new Date();
console.log(date1.getSeconds());
}, 1000)
為了解決這個問題,就可以通過H5引入的Web Workes來解決,也能解決一些比較函數(shù)的計算.
Web Workers是運(yùn)行在后臺的JS代碼,不會影響頁面的性能,創(chuàng)建了一個worker,可以將消息發(fā)送給創(chuàng)建它的js,通過事件處理指定的業(yè)務(wù).而且worker使用的是外部JS文件
1.基本使用
worker在創(chuàng)建的時候,需要使用一個構(gòu)造函數(shù),構(gòu)造函數(shù)里需要一個參數(shù),指定外部js文件的路徑
var work = new Worker("work.js");
如果想通過work.js文件獲取數(shù)據(jù)或者計算的結(jié)果,需要給work對象添加方法監(jiān)聽,打印一下已經(jīng)創(chuàng)建好的work對象,里面會有兩部分,一個是onmessage,用來接收外部js文件發(fā)送的數(shù)據(jù),另一個是onerror,用來處理錯誤
// work.js代碼
function timedCount()
{
var currentDate = null;
currentDate = new Date();
postMessage(currentDate.getSeconds());
setTimeout("timedCount()",1000);
}
timedCount();
這個方法就是獲取對應(yīng)的秒,然后把秒進(jìn)行返回.這里用了一個方法postMessage,這個方法能直接把值發(fā)送到work對象綁定的onmessage方法上,setTimeout用來循環(huán)調(diào)用方法,模擬setInterval.這里如果使用setInterval,計時器越來越多,瀏覽器也受不了啊.
// index.html的js代碼
work.onmessage = function(event) {
console.log(event.data);
}
事件對象event.data就是從postMessage發(fā)送過來的值.還有可以通過下面方式在html頁面里綁定事件
work.addEventListener("message", function(event) {
console.log(event.data);
}, false);
2.終止worker
在html里可以通過函數(shù)terminate()終止worker接受消息,一旦使用了terminate之后,無法重新啟用,只能重新的創(chuàng)建
work.onmessage = function(event) {
if(event.data == 12){
work.terminate();
}
console.log(event.data);
}
網(wǎng)上有的博客里寫在worker里能使用close()方法也能停止,不過不好用
3.異步計算
通過worker可以計算一些比較復(fù)雜的計算,然后可以把計算結(jié)果返回,而且會把這個計算放到任務(wù)隊(duì)列里
work.onmessage = function(event) {
console.log(event.data);
}
console.log(1);
worker.js代碼
function test(){
var count = 0;
for(var i = 0; i <100000; i++){
count +=i
}
postMessage(count);
}
test()
打印完之后先打印的是1,然后是計算,系統(tǒng)會把worker里的復(fù)雜計算放到任務(wù)隊(duì)列里,等到主線程的運(yùn)算進(jìn)行完,在執(zhí)行任務(wù)隊(duì)列里的任務(wù),也能實(shí)現(xiàn)異步的操作
4.實(shí)現(xiàn)ajax
就是把a(bǔ)jax請求的過程都放到worker里去執(zhí)行,獲取數(shù)據(jù)之后,在通過postMessage()方法發(fā)送請求過來的數(shù)據(jù),下面是對應(yīng)的代碼實(shí)現(xiàn)
var work = new Worker("work.js");
// 把請求方式和地址作為參數(shù)發(fā)送給worker文件
work.postMessage({
type:"get",
url:"work.php"
});
work.onmessage = function(event) {
console.log(event.data);
}
work.js代碼
addEventListener("message", function(event){
var obj = event.data;
var request = new XMLHttpRequest();
obj.type = obj.type || "get";
obj.data = obj.data || {};
if(obj.type.toLowerCase() == "get"){
var path = pathAdd("get", obj.url, obj.data);
request.open("GET", path);
request.send();
} else if(obj.type.toLowerCase() == "post"){
request.open("POST", obj.url);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var data = pathAdd("post", obj.url, obj.data);
request.send(data);
}
request.onreadystatechange = function(){
if(request.status == 200 && request.readyState == 4){
postMessage(request.responseText);
}
}
})
function pathAdd(type, url, data){
var arr = [];
for (var i in data) {
arr.push(i+"="+data[i]);
}
if(type == "get"){
return url+"?"+arr.join("&");
} else {
return arr.join("&");
}
}
5.DedicatedWorkerGlobalScope
worker.js里,有一個自己的作用域,打印self,在之前,self一般指的是window,但是在worker里,self指的是一個叫DedicatedWorkerGlobalScope的對象,包括添加的方法和發(fā)送的信息都是由這個對象來完成.如果想在這個作用域里引用一下功能的函數(shù),可以使用importScripts()來引入
6.注意
還是有一些東西需要注意一樣:
1.Web Worker無法訪問DOM節(jié)點(diǎn)蕉扮;
2.Web Worker無法訪問全局變量或是全局函數(shù)宣蔚;
3.Web Worker無法調(diào)用alert()或者confirm之類的函數(shù);
4.Web Worker無法訪問window土浸、document之類的瀏覽器全局變量
但是Web Worke里可以訪問navigator對象里的一些屬性appName,appVersion,platform,userAgent