事件迴圈(EventLoop)的學習總結
阿新 • • 發佈:2018-12-26
前言
在學習eventloop之前,我們需要複習一下js的單執行緒和非同步。
雖說js是單執行緒的,但是在瀏覽器和Node中都做了相應的處理。如瀏覽器中的web workers(工作執行緒),Node中的child_process(子程序)。它們的出現對大量計算的分解起到了促進作用。
事件迴圈
當程序啟動時,Node會建立一個tick迴圈,每個tick迴圈通過內部的觀察者來檢視是否有事件需要處理,如果有就取出事件和它相關的回撥函式去執行,執行完以後就進入下一個迴圈,如果不再有就退出程序。
瀏覽器中的eventloop
在瀏覽器中把非同步事件放到工作執行緒中,避免阻塞主執行緒UI的渲染
console.log('程序開始') const ajax = new XMLHttpRequest() ajax.addEventListener('load', () => { console.log('load') }) ajax.addEventListener('loadend', () => { if (ajax.readyState == 4 && ajax.status == 200) { console.log('ajax success') } else { console.log('ajax success') } }) ajax.open('get', 'http://localhost/study/html/vue.js') ajax.send() setTimeout(() => { console.log('setTimeout') }, 300) fetch('http://localhost/study/html/demo.json',{ headers: { 'content-type': 'application/json' } }).then(res => { console.log('fetch') }) let i = 0 while(i < 10000) { i++ } console.log(i) console.log('程序結束')
從結果可以看出三種非同步處理不阻塞主執行緒程式碼的執行,而ajax、fetch、setTimeout根據程式碼處理結束的先後來執行回撥函式。
Nodejs中的eventloop
Node中的事件迴圈根據觀察者的優先順序來執行,同一個迴圈內的process.nextTick -> setTimeout -> setImmediate
setTimeout(() => { console.log('setTimeout') }, 0) setImmediate(() => { console.log('setImmediate1') process.nextTick(() => { console.log('setImmediate1 插入nextTick') }) }) setImmediate(() => { console.log('setImmediate2') }) process.nextTick(() => { setTimeout(() => { console.log('nextTick1 setTimeout') }, 100) console.log('nextTick1') }) process.nextTick(() => { console.log('nextTick2') }) console.log('正常執行')
總結
事件迴圈的執行特點,源於利用單執行緒,遠離多執行緒死鎖、狀態同步等問題;利用非同步讓單執行緒遠離阻塞,以更好的使用CPU。