再談JavaScript線程
代碼判斷一:
<div id="div">
click me
</div>
<script>
var div=document.getElementById("div");
div.addEventListener('click',function(){
alert('You have clicked me!');
});
for(var i =0; i<999999999;i++){
console.log(i);
}
</script>
執(zhí)行之,不出意外的話所有瀏覽器都會卡死,因?yàn)樯厦娴膄or循環(huán)次數(shù)太多了,非常耗費(fèi)CPU資源,而基于JavaScript單線程的事實(shí),瀏覽器UI渲染被掛起而導(dǎo)致假死。
現(xiàn)在問題來了,我就是想要實(shí)現(xiàn)上述代碼,怎么辦?
Concurrent.Thread.js
該類庫實(shí)質(zhì)上還是使用setTimeout來實(shí)現(xiàn)一個(gè)“假的多線程”。在HTML5 WebWorker問世之前是一個(gè)很好的選擇。比如我們要實(shí)現(xiàn)上述“代碼片段一”,可以這樣寫(點(diǎn)我下載類庫):
代碼片段二:
<div id="div">
click me
</div>
<script src="Concurrent.Thread.js"></script>
<script>
Concurrent.Thread.create(function(){
var div=document.getElementById("div");
div.addEventListener('click',function(){
alert('You have clicked me!');
});
for(var i =0; i<9999999;i++){
console.log(i);
}
});
</script>
通過該類庫提供的create方法可以創(chuàng)建一個(gè)“新線程”。另外,給script標(biāo)簽的type屬性設(shè)置為 text/x-script.multithreaded-js 也可以實(shí)現(xiàn)同樣的效果:
代碼片段三:
<div id="div">
click me
</div>
<script src="Concurrent.Thread.js"></script>
<script type="text/x-script.multithreaded-js">
var div=document.getElementById("div");
div.addEventListener('click',function(){
alert('You have clicked me!');
});
for(var i =0; i<9999999;i++){
console.log(i);
}
</script>
WebWorker
針對以上瀏覽器卡死這種糟糕的用戶體驗(yàn),HTML5怎么會熟視無睹呢?
下面我們用經(jīng)典的斐波那契數(shù)列來做測試:
代碼片段四:
主頁面:
<div id="div"></div>
<script>
window.onload=function(){
var div=document.getElementById("div");
if(typeof(Worker)!=="undefined"){//在創(chuàng)建WebWorker之前,先判斷瀏覽器是否支持
console.log("Start calculating....");
var time1= new Date()*1;//獲得當(dāng)前時(shí)間戳
var worker=new Worker("fibonacci.js");//創(chuàng)建WebWorker對象,并傳遞在新線程中將要執(zhí)行的腳本的路徑
worker.onmessage=function(e){ //監(jiān)聽從新線程發(fā)送過來的數(shù)據(jù)
div.innerHTML=e.data;
var time2=new Date()*1;
console.log("time spend:"+(time2-time1)+"ms");
}
worker.postMessage(36);//向新線程發(fā)送數(shù)據(jù)
}else{
alert("Your browser do not support WebWoker");
}
}
</script>
fibonacci.js:
var fibonacci=function (n){
return n<3?n:(arguments.callee(n-1)+arguments.callee(n-2));
}
onmessage=function(e){
var num=parseInt(e.data,10);
postMessage(fibonacci(num));//向主頁面發(fā)送數(shù)據(jù)
}
基本的使用方法已在代碼中做注釋了,查看控制臺,可以看見很快就打印出執(zhí)行時(shí)間了。所以我們得出的結(jié)論是:WebWorker適合在前端執(zhí)行復(fù)雜的大量的計(jì)算。需要注意的是,WebWorker不支持跨域,本地測試還是用http協(xié)議,不要用file協(xié)議,否則不能創(chuàng)建Worker對象而報(bào)腳本錯(cuò)誤 。

如果我們需要連續(xù)執(zhí)行多個(gè)postMessage操作,最好不要work.postMessage一直寫,像這樣:
worker.postMessage(36);
worker.postMessage(36);
worker.postMessage(36);
因?yàn)榇藭r(shí)只有一個(gè)WebWorker實(shí)例,postMessage會順序執(zhí)行而不是異步執(zhí)行,就不能充分發(fā)揮它的性能了??梢酝ㄟ^創(chuàng)建多個(gè)WebWorker實(shí)例來發(fā)送數(shù)據(jù)。
需要注意的幾點(diǎn)事項(xiàng)有:
1、我們觀察到WebWorker通過接受一個(gè)url來創(chuàng)建一個(gè)worker,而jsonp的實(shí)現(xiàn)原理就是通過動(dòng)態(tài)插入script標(biāo)簽加載數(shù)據(jù),那我們嘗試用WebWorker來實(shí)現(xiàn)同樣的事情不是更好嗎?因?yàn)閃ebWorker是多線程的,沒有阻塞,豈不美哉?但實(shí)際上經(jīng)過實(shí)驗(yàn),我們發(fā)現(xiàn)WebWorker表現(xiàn)并不如意。所以這并不是它擅長的事,我們還是不要讓它越俎代庖的好。
2、WebWorker在接受其他來源信息的時(shí)候,其實(shí)也給站點(diǎn)的安全帶來了隱患,如果接收不明來源的腳本信息,可能會導(dǎo)致XSS注入攻擊。所以這點(diǎn)需要防范,其實(shí)我們上面例子中使用innerHTML是不安全的,可以使用innerText或現(xiàn)代瀏覽器提供的textContent來替代,以過濾掉html標(biāo)簽。
今天比較累了,想睡覺了,先寫這么多吧。
相關(guān)文章
javascript操作table(insertRow,deleteRow,insertCell,deleteCell方
本篇文章主要介紹了javascript操作table(insertRow,deleteRow,insertCell,deleteCell方法)需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12
js實(shí)現(xiàn)表格數(shù)據(jù)搜索
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)表格數(shù)據(jù)搜索,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
ie7+背景透明文字不透明超級簡單的實(shí)現(xiàn)方法
這篇文章主要介紹了ie7+背景透明文字不透明超級簡單的實(shí)現(xiàn)方法,有需要的朋友可以參考一下2014-01-01
JS實(shí)現(xiàn)控制表格只顯示行邊框或者只顯示列邊框的方法
這篇文章主要介紹了JS實(shí)現(xiàn)控制表格只顯示行邊框或者只顯示列邊框的方法,涉及javascript使用表格對象的rules屬性的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
基于JavaScript實(shí)現(xiàn)類似于百度學(xué)術(shù)高級檢索功能
這篇文章主要介紹了基于JavaScript實(shí)現(xiàn)類似于百度學(xué)術(shù)高級檢索功能 的相關(guān)資料,需要的朋友可以參考下2016-03-03

