這裏就很少說了,主要說僞線程。由於web worker不能操做dom元素,不少時候用不上。javascript
重點:
瀏覽器的內核是多線程的,一個瀏覽器通常至少實現三個常駐線程:javascript引擎線程,GUI渲染線程,瀏覽器事件觸發線程。java
a.javascript引擎是基於事件驅動單線程執行的,JS引擎一直等待着任務隊列中任務的到來,而後加以處理,瀏覽器不管何時都只有一個JS線程在運行JS程序。
b.GUI渲染線程負責渲染瀏覽器界面,當界面須要重排、重繪或因爲某種操做引起迴流時,該線程就會執行。但須要注意 GUI渲染線程與JS引擎是互斥的,當JS引擎執行時GUI線程會被掛起,GUI更新會被保存在一個隊列中等到JS引擎空閒時當即被執行。
c.事件觸發線程,當一個事件被觸發時該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理。這些事件可來自JavaScript引擎當前執行的代碼塊如setTimeOut、也可來自瀏覽器內核的其餘線程如鼠標點擊、AJAX異步請求等,但因爲JS的單線程關係全部這些事件都得排隊等待JS引擎處理。web
當咱們要循環過百萬級的數據甚至億的時候怎麼辦?
那就用setTimeout模擬一個多線程。
重點:js的工做機制是:當線程中沒有執行任何同步代碼的前提下才會執行異步代碼,setTimeout是異步代碼,因此setTimeout只能等js空閒纔會執行,但死循環是永遠不會空閒的,因此setTimeout也永遠不會執行。即便setTimeout爲0,他也是等js引擎的代碼執行完以後纔會插入到js引擎線程的最後執行。
上栗子數組
var thread = function () { var nowTime = 0, //線程已經執行了多久 maxTime = 15;//線程最多執行多久 var threadArr = [];//數組模擬線程隊列 this.addThread = function (fn) { threadArr.push(fn) } this.start=function () { doingThread(); } var doingThread = function () { if (threadArr.length > 0) { if (nowTime < maxTime) { let now = new Date().getTime(); var method = threadArr[0]; method(); threadArr.splice(0, 1); let nowNew = (new Date().getTime() - now); nowTime += nowNew; doingThread(); } else {//每執行完線程後睡1ms nowTime=0; setTimeout(doingThread, 1); } }else {//先睡着等待線程隊列 setTimeout(doingThread,100) } } } var fn = function (num) { console.log(num) } var thread = new thread(); thread.start() for (let i = 0; i < 1000000; i++) { thread.addThread(function () { fn(i) }) }
循環百萬級的數據量而且不阻塞Ui線程是徹底沒問題的,但過億瀏覽器仍是會蹦。(這裏只是提供個簡單的思路,其實過億也能夠不蹦)瀏覽器