講述目的:本文章針對JS萌新,是要用最簡單的解釋讓讀者能夠判斷在函數語句的執行順序,不涉及關於js更深層的理解和探討也不花費精力講解js為什么會將執行任務有這些區分,只討論任務的執行順序,保護讀者不被各種概念繞暈,大神可繞道。
講述思路:
1.簡單理解同步異步、宏任務和微任務
2.執行順序判斷方法
3.簡單實例分析
4.稍復雜點的實例分析
正文開始:
1.簡單理解同步異步、宏任務和微任務
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因是第二層異步語句,會被放到之后才執行。
執行結果為