日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

【worker】js中的多线程

發(fā)布時(shí)間:2025/7/25 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【worker】js中的多线程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ? 因?yàn)橄聜€(gè)項(xiàng)目中要用到一些倒計(jì)時(shí)的功能,所以就提前準(zhǔn)備了一下,省的到時(shí)候出現(xiàn)一下界面不友好和一些其他的事情。正好趁著這個(gè)機(jī)會(huì)也加深一下html5中的多線程worker的用法和理解。

Worker簡(jiǎn)介

? ? JavaScript 語(yǔ)言采用的是單線程模型,也就是說(shuō),所有任務(wù)只能在一個(gè)線程上完成,一次只能做一件事。前面的任務(wù)沒做完,后面的任務(wù)只能等著。這些都是我們所公知的。但是隨著業(yè)務(wù)的不斷增加,只是單純的單線程模式已經(jīng)可能無(wú)法滿足我們的需求了。于是在html5中新增了后臺(tái)任務(wù)worker API。

w3c中的介紹:web worker 是運(yùn)行在后臺(tái)的 JavaScript,獨(dú)立于其他腳本,不會(huì)影響頁(yè)面的性能。您可以繼續(xù)做任何愿意做的事情:點(diǎn)擊、選取內(nèi)容等等,而此時(shí) web worker 在后臺(tái)運(yùn)行。

? ? ? ?worker就是為了JavaScript 創(chuàng)造多線程環(huán)境,允許主線程創(chuàng)建 Worker 線程,將一些任務(wù)分配給后者運(yùn)行。開啟后臺(tái)線程,在不影響前臺(tái)線程的前提下做一些耗時(shí)或者異步的操作。因?yàn)槭遣煌木€程,所以主線程與worker線程互不干擾。也不會(huì)相互打斷。所以在一些場(chǎng)景可以提高頁(yè)面的流程性。Worker 線程一旦新建成功,就會(huì)始終運(yùn)行,不會(huì)被主線程上的活動(dòng)(比如用戶點(diǎn)擊按鈕、提交表單)打斷。這樣有利于隨時(shí)響應(yīng)主線程的通信。但是,這也造成了 Worker 比較耗費(fèi)資源,不應(yīng)該過度使用,而且一旦使用完畢,就應(yīng)該關(guān)閉。

使用規(guī)則

  • 必須同源:也就是說(shuō)js文件的路徑必須和主線程的腳本同源。防止了外部引用。
  • dom限制:在worker線程中不能操作dom(document,window,parent)。注意可以使用瀏覽器的navigator和location對(duì)象。
  • 通訊限制:worker線程和主線程不在一個(gè)上下文中所以不能直接通訊。也就是說(shuō)主線程定義的變量在worker中也是不能使用的。所有只能通過消息完成。
  • 提示禁止:worker線程不能alert和confirm,這個(gè)不知到具體原因?
  • 傳值dom:進(jìn)行消息通訊也不能傳值dom只能是變量。
  • ie限制:ie9不能使用!ie9不能使用!ie9不能使用!
  • worker文檔

    Web Workers API的Worker界面代表了一個(gè)可以輕松創(chuàng)建的后臺(tái)任務(wù),可以將消息發(fā)送回其創(chuàng)建者。創(chuàng)建worker就像調(diào)用?構(gòu)造函數(shù)并指定要在工作線程中運(yùn)行的腳本一樣簡(jiǎn)單。

    構(gòu)造函數(shù)

    worker():創(chuàng)建一個(gè)專用的Web worker,在指定的URL上執(zhí)行腳本。示例:var?worker=new Worker('js/setTime.js');

    屬性

    onerror:

    這是一個(gè)在error事件發(fā)生時(shí)調(diào)用的函數(shù),并且通過該函數(shù)冒泡worker。示例:worker.οnerrοr=function(){....};

    onmessage

    ? 這是一個(gè)worker中message事件要發(fā)生的時(shí)候調(diào)用的事件。? 示例:worker.onmessage=function(){....};

    ? 這個(gè)事件一般與postMessage事件同時(shí)使用,一個(gè)用來(lái)發(fā)送數(shù)據(jù),一個(gè)用來(lái)接受數(shù)據(jù)。例如:

    ?主線程中:

    var jsId = "00001";var worker = new Worker('js/setTime.js');worker.postMessage(jsId);

    ?

    ? ? ? ? ?worker線程中:

    //接受事件參數(shù) onmessage = function(e) {console.log(e.data[0]) }

    這樣就完成了一個(gè)主線程向worker線程傳遞參數(shù)的過程。同樣如果worker線程要向主線程傳遞參數(shù)反過來(lái)寫即可。

    ?onmessageerror:

    在消息傳遞過程出現(xiàn)錯(cuò)誤的屬性事件。示例:worker.onmessageerror=function(){....};

    方法

    postMessage:

    向線程worker的內(nèi)部范圍發(fā)送消息,可以設(shè)置參數(shù),發(fā)送給worker線程的數(shù)據(jù)。在onmessage中接受。

    terminate:

    過多的開啟worker線程非常浪費(fèi)資源所以在使用過后可以終止它,終止方法使用terminate()。示例:worker.terminate();

    close:

    除了上面的關(guān)閉,如果是在worker線程自身也可以使用self.close()關(guān)閉。

    ?計(jì)時(shí)器示例

    上面說(shuō)了那么多都是介紹worker的一些基本屬性或者方法的使用。下面通過具體的示例來(lái)看效果。

    我們就拿最常用的倒計(jì)時(shí)來(lái)做示例說(shuō)明。很簡(jiǎn)單的一個(gè)例子。我們?cè)跇I(yè)務(wù)中經(jīng)常遇到倒計(jì)時(shí)業(yè)務(wù),在倒計(jì)時(shí)的時(shí)候還要做一些其他的業(yè)務(wù)。因?yàn)閖s單線程的特性,你會(huì)發(fā)現(xiàn)你的倒計(jì)時(shí)在你進(jìn)行其他業(yè)務(wù)操作的時(shí)候是暫停了的。例如現(xiàn)在是9:57你進(jìn)行了三秒的業(yè)務(wù)處理。等業(yè)務(wù)處理完成應(yīng)該是:9:54,但是你的倒計(jì)時(shí)還是9:57.就很明顯的說(shuō)明了這一個(gè)現(xiàn)象。

    場(chǎng)景業(yè)務(wù)設(shè)計(jì)

    那么我們現(xiàn)在設(shè)計(jì)這么一個(gè)業(yè)務(wù)操作,

    • 首先我們頁(yè)面有一個(gè)定時(shí)器和一個(gè)業(yè)務(wù)操作按鈕(用來(lái)模擬耗時(shí)的操作)。
    • 然后把定時(shí)器寫到一個(gè)worker中進(jìn)行倒計(jì)時(shí)操作。
    • 最后通過消息通訊把每次的倒計(jì)時(shí)時(shí)間發(fā)送給主線程讓主線程修改顯示時(shí)間。
    • 結(jié)束倒計(jì)時(shí)完畢結(jié)束定時(shí)器和線程

    ?有人可能會(huì)說(shuō)為什么還要回到主線程修改時(shí)間顯示值,請(qǐng)看一下上面的使用規(guī)則,我本來(lái)也是打算進(jìn)行主線程傳值dom給worker線程奈何不行只能在回傳回來(lái)。

    代碼展示

    ?Html代碼:

    <body><div><span id="Minute_p">10</span> :<span id="Second_p">00</span></div><button type="button" οnclick="business()">耗時(shí)操作</button>
    </body>

    主線程js代碼:

    //頁(yè)面加載完成后初始化window.onload = function() {//創(chuàng)建定時(shí)器線程var worker = new Worker('js/setTime.js');//獲取dom對(duì)象var domMinute_p = document.getElementById('Minute_p');var domSecond_p = document.getElementById('Second_p');worker.postMessage(600);//這里可以接受worker線程的返回值worker.onmessage = function(event) {var totalSecond = event.data;console.log(totalSecond)//計(jì)算分鐘數(shù)var minute_p = parseInt(totalSecond / 60);domMinute_p.innerText = minute_p;//計(jì)算秒數(shù)var second_p = parseInt(totalSecond % 60);domSecond_p.innerText = second_p;}}//這里是模擬的耗時(shí)操作function business() {var data = [1, 2, 3, 4, 5];for(var i = 1; i < 1000; i++) {for(var j = 1; j < 1000; j++) {for(var k = 1; k < 5000; k++) {var b = k * 100;}}}console.log("業(yè)務(wù)終于走完了!")}

    worker線程js代碼:

    var totalSecond = 600; var domMinute_p, domSecond_p,//接受事件參數(shù)onmessage = function(e) {console.log(e.data)domMinute_p = e.data;} var timeId = setInterval(function() {totalSecond--;if(totalSecond == 0) {self.close();}console.log(totalSecond)postMessage(totalSecond)}, 1000)

    好了大致示例就是這么多。下面是截圖效果:

    ?開始運(yùn)行后編號(hào)1會(huì)開始倒計(jì)時(shí),但是當(dāng)你點(diǎn)擊了編號(hào)2進(jìn)行了模擬耗時(shí)后,編號(hào)1還是會(huì)卡住,只有完成編號(hào)2后才會(huì)運(yùn)行,但是不同與上面說(shuō)到的單線程是,他再次運(yùn)行時(shí)的時(shí)間是正確時(shí)間,還是剛才的例子如果是9:57,點(diǎn)擊編號(hào)2模擬耗時(shí)了3秒,耗時(shí)完成后編號(hào)1會(huì)顯示9:54而不是單線程的9:57。就說(shuō)明worker現(xiàn)在在耗時(shí)操作的時(shí)候是持續(xù)運(yùn)行的,時(shí)間卡只不過是主線程的dom操作被卡住了而已(可以把耗時(shí)業(yè)務(wù)也開啟worker就不卡住了)。這里只是介紹worker的使用,所有就不糾結(jié)這個(gè)界面顯示的問題。

    補(bǔ)充界面顯示方法:

    后來(lái)有些人就問我怎弄界面顯示,我還是真的心疼你們啊,不知道舉一反三嗎,當(dāng)然是吧業(yè)務(wù)耗時(shí)也放到后臺(tái)線程啊,哈哈!!!

    再特此說(shuō)明一個(gè)問題,僅在安卓測(cè)試:就是定時(shí)器在息屏模式下仍繼續(xù)執(zhí)行

    我還是上面的例子做個(gè)例子:

    把耗時(shí)業(yè)務(wù)放到business.js文件

    onmessage = function(e) {console.log(e.data)for(var i = 1; i < 1000; i++) {for(var j = 1; j < 1000; j++) {for(var k = 1; k < 5000; k++) {var b = k * 100;}}}console.log("耗時(shí)業(yè)務(wù)走完了");postMessage(1) }

    然后主文件js調(diào)用就好了啊:

    //這里是模擬的耗時(shí)操作 function business() {var worker = new Worker('js/business.js');worker.postMessage("開啟任務(wù)耗時(shí)");worker.onmessage = function(event) {if(event == 1) {console.log("點(diǎn)擊一次完成")worker.terminate()}}}

    截圖效果:

    ?

    作者:YanBigFeg —— 顏秉鋒

    出處:http://www.cnblogs.com/yanbigfeg

    本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)標(biāo)明出處。如果您覺得本篇博文對(duì)您有所收獲,覺得小弟還算用心,請(qǐng)點(diǎn)擊右下角的 [推薦],謝謝!

    《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

    總結(jié)

    以上是生活随笔為你收集整理的【worker】js中的多线程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。