講述目的:本文章針對JS萌新,是要用最簡單的解釋讓讀者可以判斷在函數語句的執行順序,不涉及關於js更深層的理解和探討也不花費精力講解js爲何會將執行任務有這些區分,只討論任務的執行順序,保護讀者不被各類概念繞暈,大神可繞道。ajax
講述思路:promise
1.簡單理解同步異步、宏任務和微任務異步
2.執行順序判斷方法函數
3.簡單實例分析spa
4.稍複雜點的實例分析線程
正文開始:code
1.簡單理解同步異步、宏任務和微任務blog
js是單線程的,全部的任務都要排隊挨個執行,就比如作保健(執行js代碼),保健師傅只有一個(單線程),顧客(js代碼)需排隊享受服務,排隊的順序按照顧客的種類(同步異步、宏任務微任務)和顧客到店順序(在代碼中的位置)執行;隊列
同步與異步、宏任務和微任務分別是函數兩個不一樣維度的描述。事件
異步任務:setTimeout和setInterval、ajax、事件綁定等
同步任務:除了異步任務外的全部任務
微任務:process.nextTick和 Promise後的theny語句和catch語句等
宏任務:除了微任務之外的全部任務
2.執行順序判斷方法
先同步再異步,在此基礎上先宏任務再微任務
3.簡單實例分析
1 setTimeout(function () { 2 new Promise(function (resolve, reject) { 3 console.log('異步宏任務promise'); 4 resolve(); 5 }).then(function () { 6 console.log('異步微任務then') 7 }) 8 console.log('異步宏任務'); 9 }, 0) 10 new Promise(function (resolve, reject) { 11 console.log('同步宏任務promise'); 12 resolve(); 13 }).then(function () { 14 console.log('同步微任務then') 15 }) 16 console.log('同步宏任務')
結果
分析:setTimeout是異步任務,雖然他在0秒後執行但仍排在隊列的後面,所以其中的代碼所有靠後執行;new Promise是同步任務同時也是主任務,所以第一行先打印'同步宏任務promise',then是微任務因此靠後執行,先執行第16行代碼,以後再執行第13行的then語句,所以第二行輸出爲'同步宏任務',第三行爲'同步微任務then';接下來執行setTimeout中的語句,then由於是微任務因此在第8行執行完成後再執行。
4.稍複雜點的實例分析
1 setTimeout(() => { 2 console.log('異步1任務time1'); 3 new Promise(function (resolve, reject) { 4 console.log('異步1宏任務promise'); 5 setTimeout(() => { 6 console.log('異步1任務time2'); 7 }, 0); 8 resolve(); 9 }).then(function () { 10 console.log('異步1微任務then') 11 }) 12 }, 0); 13 console.log('主線程宏任務'); 14 setTimeout(() => { 15 console.log('異步2任務time2'); 16 17 }, 0); 18 new Promise(function (resolve, reject) { 19 console.log('宏任務promise'); 20 // reject(); 21 resolve(); 22 }).then(function () { 23 console.log('微任務then') 24 }).catch(function () { 25 console.log('微任務catch') 26 }) 27 console.log('主線程宏任務2');
本例中需注意第9行的then是在第14行的setTimeout以前執行的,而第5行的setTimeout在第14行以後執行。也就是在一個異步任務代碼塊中,會先執行完全部同步語句(包括宏任務和微任務),而後去執行整個代碼中的同級別的異步任務,而第5行的setTimeout因是第二層異步語句,會被放到以後才執行。
執行結果爲