Web高級 Eventloop和事件執行順序

1. EventLoop

1.1 調用棧

當一個方法執行時內部調用另外的方法,則會造成調用棧,如圖:javascript

1.2 任務隊列

JavaScript有一個主線程執行當前任務,主線程的代碼同步執行,並把遇到的事件和回調註冊到事件表中。
當事件表中的事件被觸發時,將會把對應的處理函數推送到任務隊列當中。html

每一次EventLoop會從任務隊列中獲取最前面的事件處理函數進行執行。java

  • macrotasks queue(圖中task queue)
    包括: 總體代碼script,setTimeout,setInterval,setImmediate,I/O,UI渲染
  • microtasks queue
    包括: Promise process.nextTick Object.observe MutationObserver

注意:每一次Eventloop擁有獨立的微任務隊列,在每次同步調用堆棧結束後,會檢查微任務隊列中是否有須要處理的事件,若是有就進行調用.node

1.3 事件循環

當一輪事件循環結束後(Fun1),進行下一輪循環(Fun2).git

事件執行順序

根據macrotasks隊列和microtasks隊列的執行時機不一樣,所以須要注意異步代碼的執行順序github

其原則是:web

  1. macrotasks將進入宏任務隊列,將在下一次eventloop時進行調用(先進先出)
    常見的包括XHR,JSONP,setTimeout,setInterval等
  2. microtasks將進入微任務隊列,在當前eventloop結束前進行調用
    microtasks常見的有Promise.then,process.nextTick(nodejs)等
console.log(1)
setTimeout(()=>{console.log(2)},0);
Promise.resolve(console.log(3)).then(()=>{console.log(4)});
var ps = new Promise((resolve,reject)=>{console.log(5);resolve(1)});
ps.then(()=>{console.log(6)});
var fs = new Promise((filename)=>{return file.read(filename)});
fs.then((rs)=>{console.log(7)});
//1,3,5,4,6,7,2

refs:
https://github.com/ccforward/cc/issues/48
https://html.spec.whatwg.org/multipage/webappapis.html#task-queueapi

相關文章
相關標籤/搜索