js是單線程,單線程中又分為同步任務(wù)憾朴,異步任務(wù)狸捕。
同步任務(wù):在主線程上執(zhí)行,前面任務(wù)沒有執(zhí)行完畢众雷,后面的任務(wù)將一直等待執(zhí)行灸拍。
異步任務(wù):則是放在任務(wù)隊(duì)列中做祝,等待主線程所有任務(wù)執(zhí)行完成后,通知任務(wù)隊(duì)列把可執(zhí)行的任務(wù)放到主線程上執(zhí)行鸡岗。異步任務(wù)放到主線程執(zhí)行完成后混槐,又通知任務(wù)隊(duì)列把下一個(gè)任務(wù)放到主線程中執(zhí)行。這個(gè)過程一直持續(xù)轩性,直到所有的異步任務(wù)執(zhí)行完畢声登,這個(gè)持續(xù)重復(fù)的過程就稱為event loop,而一次循環(huán)就是一次tick揣苏。
異步任務(wù)又分為宏任務(wù)悯嗓、微任務(wù)。
宏任務(wù)(macrotask):script代碼卸察、setTimeout脯厨、 setInterval等。
微任務(wù)(microtask):Promise坑质, process.nextTick合武, Object.observe, MutationObserver洪乍。
執(zhí)行過程:先執(zhí)行宏任務(wù)眯杏,再執(zhí)行微任務(wù)。
微任務(wù)是一次循環(huán)中壳澳,一直取一直取,直到所有的微任務(wù)隊(duì)列全部執(zhí)行完茫经。宏任務(wù)巷波,則是循環(huán)一次取一次。
如果在事件循環(huán)的過程中卸伞,又加了macrotask抹镊,則是將macrotask放到隊(duì)尾,等到下一次循環(huán)荤傲,再執(zhí)行垮耳,如果是microtask,則是放在本次循環(huán)的microtask隊(duì)列的隊(duì)尾遂黍,直到microtask隊(duì)列清空终佛。
console.log(1);
setTimeout(function () {
console.log(2)
}, 0);
new Promise(function (resolve) {
console.log(3)
for (var i = 100; i > 0; i--) {
i == 1 && resolve()
}
console.log(4)
}).then(function () {
console.log(5)
}).then(function () {
console.log(6)
});
console.log(7);
- 因?yàn)閟cript是宏任務(wù),所以先放入到宏任務(wù)隊(duì)列雾家,優(yōu)先執(zhí)行铃彰,輸出1。
- 接下來遇到setTimeout芯咧,因?yàn)閟etTimeout是宏任務(wù)牙捉,會放到下一次異步任務(wù)隊(duì)列中竹揍。
- 初始化promise實(shí)例過程是同步任務(wù),promise.then 是微任務(wù)邪铲,所以會輸出3芬位,4。繼續(xù)向下執(zhí)行带到,promise.then 是微任務(wù)晶衷,放到本次循環(huán)的微任務(wù)隊(duì)列尾部。
- 繼續(xù)向下執(zhí)行阴孟,遇到了console.log(7) 輸出7晌纫。直到現(xiàn)在本次循環(huán)結(jié)束,再檢查微任務(wù)中是否還有任務(wù)永丝,確實(shí)還有上一次的promise.then 锹漱,輸出5,6
- 本次循環(huán)結(jié)束慕嚷,繼續(xù)下一次宏任務(wù)哥牍,setTimeout 輸出2。
結(jié)果是:1喝检、3嗅辣、4、7挠说、5澡谭、6、2