日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

主进程中发生了一个javascript错误_知道html5 Web Worker标准吗?能实现JavaScript的多线程?

發(fā)布時(shí)間:2023/12/13 javascript 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 主进程中发生了一个javascript错误_知道html5 Web Worker标准吗?能实现JavaScript的多线程? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

js為什么是單線程?

主要是因?yàn)樽铋_始javascript是單純的服務(wù)于瀏覽器的一種腳步語(yǔ)言(那時(shí)候沒有nodejs)。瀏覽器是為了渲染網(wǎng)頁(yè),通過(guò)dom與用戶交互,如果一個(gè)線程需要給dom執(zhí)行click事件,而另一個(gè)進(jìn)程要?jiǎng)h除這個(gè)dom,這2個(gè)動(dòng)作可能同時(shí)進(jìn)行,也可能先后進(jìn)行(像java,c#等語(yǔ)言中會(huì)引入鎖的概念,這樣會(huì)變得異常復(fù)雜),那么就會(huì)造成很多不可預(yù)料的錯(cuò)誤。

所以,為了避免復(fù)雜性,從一誕生,JavaScript就是單線程,這已經(jīng)成了這門語(yǔ)言的核心特征。為了利用多核CPU的計(jì)算能力,HTML5提出Web Worker標(biāo)準(zhǔn),允許JavaScript腳本創(chuàng)建多個(gè)線程,但是子線程完全受主線程控制,且不得操作DOM。所以,這個(gè)新標(biāo)準(zhǔn)并沒有改變JavaScript單線程的本質(zhì)。

瀏覽器是多線程的

瀏覽器打開一個(gè)tab,就會(huì)單獨(dú)開一個(gè)進(jìn)程,這個(gè)進(jìn)程包含多個(gè)線程
主要包含的線程有:

GUI渲染線程
負(fù)責(zé)渲染瀏覽器界面,解析HTML,CSS,構(gòu)建DOM樹和RenderObject樹,布局和繪制等。
當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(reflow)時(shí),該線程就會(huì)執(zhí)行
注意,GUI渲染線程與JS引擎線程是互斥的,當(dāng)JS引擎執(zhí)行時(shí)GUI線程會(huì)被掛起(相當(dāng)于被凍結(jié)了),GUI更新會(huì)被保存在一個(gè)隊(duì)列中等到JS引擎空閑時(shí)立即被執(zhí)行。JS引擎線程
也稱為JS內(nèi)核,負(fù)責(zé)處理Javascript腳本程序。(例如V8引擎)
JS引擎線程負(fù)責(zé)解析Javascript腳本,運(yùn)行代碼。
JS引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來(lái),然后加以處理,一個(gè)Tab頁(yè)(renderer進(jìn)程)中無(wú)論什么時(shí)候都只有一個(gè)JS線程在運(yùn)行JS程序
同樣注意,GUI渲染線程與JS引擎線程是互斥的,所以如果JS執(zhí)行的時(shí)間過(guò)長(zhǎng),這樣就會(huì)造成頁(yè)面的渲染不連貫,導(dǎo)致頁(yè)面渲染加載阻塞。事件觸發(fā)線程
歸屬于瀏覽器而不是JS引擎,用來(lái)控制事件循環(huán)(可以理解,JS引擎自己都忙不過(guò)來(lái),需要瀏覽器另開線程協(xié)助)
當(dāng)JS引擎執(zhí)行代碼塊如setTimeOut時(shí)(也可來(lái)自瀏覽器內(nèi)核的其他線程,如鼠標(biāo)點(diǎn)擊、AJAX異步請(qǐng)求等),會(huì)將對(duì)應(yīng)任務(wù)添加到事件線程中
當(dāng)對(duì)應(yīng)的事件符合觸發(fā)條件被觸發(fā)時(shí),該線程會(huì)把事件添加到待處理隊(duì)列的隊(duì)尾,等待JS引擎的處理
注意,由于JS的單線程關(guān)系,所以這些待處理隊(duì)列中的事件都得排隊(duì)等待JS引擎處理(當(dāng)JS引擎空閑時(shí)才會(huì)去執(zhí)行)定時(shí)觸發(fā)器線程
傳說(shuō)中的setInterval與setTimeout所在線程
瀏覽器定時(shí)計(jì)數(shù)器并不是由JavaScript引擎計(jì)數(shù)的,(因?yàn)镴avaScript引擎是單線程的, 如果處于阻塞線程狀態(tài)就會(huì)影響記計(jì)時(shí)的準(zhǔn)確)
因此通過(guò)單獨(dú)線程來(lái)計(jì)時(shí)并觸發(fā)定時(shí)(計(jì)時(shí)完畢后,添加到事件隊(duì)列中,等待JS引擎空閑后執(zhí)行)
注意,W3C在HTML標(biāo)準(zhǔn)中規(guī)定,規(guī)定要求setTimeout中低于4ms的時(shí)間間隔算為4ms。異步http請(qǐng)求線程
在XMLHttpRequest在連接后是通過(guò)瀏覽器新開一個(gè)線程請(qǐng)求
將檢測(cè)到狀態(tài)變更時(shí),如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將這個(gè)回調(diào)再放入事件隊(duì)列中。再由JavaScript引擎執(zhí)行。
上面列出的線程之間,有一個(gè)重要的規(guī)則是:GUI渲染線程與JS引擎線程互斥,那么我們可以得出以下結(jié)論JS阻塞頁(yè)面加載,那么在js運(yùn)行的這段時(shí)間內(nèi),GUI的渲染會(huì)停止,這段時(shí)間內(nèi)的界面交互,DOM的重繪與回流會(huì)停止,會(huì)被保存到待執(zhí)行隊(duì)列中,直到j(luò)s線程空閑,才會(huì)執(zhí)行這些隊(duì)列。
我們用下面的一段代碼和運(yùn)行結(jié)果來(lái)說(shuō)明這個(gè)機(jī)制:


可以看到,一開始網(wǎng)頁(yè)和動(dòng)畫正常運(yùn)行,但是開始執(zhí)行計(jì)算斐波那契數(shù)列后,動(dòng)畫就停止了,頁(yè)面也停止響應(yīng)鼠標(biāo)的click事件了,直到recurFib(40)計(jì)算出結(jié)果后,動(dòng)畫才開始繼續(xù)執(zhí)行,而期間積攢的click事件也在一起被執(zhí)行。這就解釋了GUI渲染線程與JS引擎線程互斥。由于這個(gè)弊端HTML5提出Web Worker標(biāo)準(zhǔn)。

利用Web Worker開啟一個(gè)子線程

Web Worker 有以下幾個(gè)使用注意點(diǎn)。

1.同源限制
分配給 Worker 線程運(yùn)行的腳本文件,必須與主線程的腳本文件同源。
2.DOM 限制
Worker 線程所在的全局對(duì)象,與主線程不一樣,無(wú)法讀取主線程所在網(wǎng)頁(yè)的 DOM 對(duì)象,也無(wú)法使用document、window、parent這些對(duì)象。但是,Worker 線程可以navigator對(duì)象和location對(duì)象。
3.通信聯(lián)系
Worker 線程和主線程不在同一個(gè)上下文環(huán)境,它們不能直接通信,必須通過(guò)消息完成。
4.腳本限制
Worker 線程不能執(zhí)行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 對(duì)象發(fā)出 AJAX 請(qǐng)求。
5.文件限制
Worker 線程無(wú)法讀取本地文件,即不能打開本機(jī)的文件系統(tǒng)(file:),它所加載的腳本,必須來(lái)自網(wǎng)絡(luò)。
創(chuàng)建Worker時(shí),JS引擎向?yàn)g覽器申請(qǐng)開一個(gè)子線程(子線程是瀏覽器開的,完全受主線程控制,而且不能操作DOM)
JS引擎線程與worker線程間通過(guò)特定的方式通信(postMessage API,需要通過(guò)序列化對(duì)象來(lái)與線程交互特定的數(shù)據(jù))。
下面我們用worker的相關(guān)api來(lái)解決上面卡頓的問(wèn)題。

// test.js子線程代碼// 通過(guò)監(jiān)聽message來(lái)接受主線程中的消息addEventListener('message', function(res) { // 子線程向主線程中發(fā)生消息 // 計(jì)算斐波那契數(shù)列,這個(gè)數(shù)列從第3項(xiàng)開始,每一項(xiàng)都等于前兩項(xiàng)之和。 if(res.data === 'start') { // 開始運(yùn)算 console.log('收到主線程消息,開始運(yùn)算') function recurFib(n) { if(n < 2){ // 主動(dòng)關(guān)閉子線程 // this.close() return n ; }else { return recurFib(n-1)+recurFib(n-2) } } console.time("運(yùn)算時(shí)間:") // 計(jì)算n為40的結(jié)果 var count = recurFib(40) console.timeEnd("運(yùn)算時(shí)間:") // 向主線程發(fā)送消息 console.log('運(yùn)算完畢,發(fā)送消息給主線程!') this.postMessage(count); }})

運(yùn)行結(jié)果:

可以看到整個(gè)運(yùn)行過(guò)程動(dòng)畫沒有卡頓,也能響應(yīng)click事件,所以在我們遇到大型計(jì)算的時(shí)候,請(qǐng)單獨(dú)開啟一個(gè)worker子線程來(lái)解決js線程阻塞GUI線程的問(wèn)題。上文中只涉及到一部分worker API。

兼容性


可以看到除了Opera Mini瀏覽器,連IE都能使用了,所以兼容性問(wèn)題不大。

總結(jié)

  • 由于javaScript的最初設(shè)計(jì)特點(diǎn),采用了單線程的運(yùn)行機(jī)制。
  • 瀏覽器是多個(gè)線程相互協(xié)作來(lái)工作的,但是GUI渲染線程與JS引擎線程互斥
  • js線程在運(yùn)行時(shí),會(huì)鎖死GUI渲染線程,為了利用多核CPU的計(jì)算能力,HTML5提出Web Worker標(biāo)準(zhǔn)。
  • Web Worker的使用有一些限制,比如說(shuō):同源限制,DOM限制,文件限制等,但能解決在js需要大量計(jì)算工作時(shí),頁(yè)面卡頓的問(wèn)題。
  • Web Worker實(shí)際上是js線程的一個(gè)子線程,理論上js還是單線程的。
  • 學(xué)習(xí)如逆水行舟,不進(jìn)則退,前端技術(shù)飛速發(fā)展,如果每天不堅(jiān)持學(xué)習(xí),就會(huì)跟不上,我會(huì)陪著大家,每天堅(jiān)持推送博文,跟大家一同進(jìn)步,希望大家能關(guān)注我,第一時(shí)間收到最新文章。

    ?

    總結(jié)

    以上是生活随笔為你收集整理的主进程中发生了一个javascript错误_知道html5 Web Worker标准吗?能实现JavaScript的多线程?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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