單線程
js是單線程的遗增,意味著他同一時(shí)間只能做一件事叫惊,也就是說(shuō)所有的任務(wù)代碼需要排隊(duì)來(lái)執(zhí)行,一個(gè)任務(wù)完成之后才能開(kāi)始下一個(gè)任務(wù)做修。
任務(wù)的排隊(duì)被稱作消息隊(duì)列霍狰。
重復(fù)執(zhí)行消息隊(duì)列中的任務(wù)的這一操作被稱作事件循環(huán)。
我們的js代碼從上往下執(zhí)行饰及,但是難免會(huì)有一些異步操作蔗坯,例如發(fā)起ajax請(qǐng)求,使用定時(shí)器操作旋炒。那么遇到異步操作時(shí)js是怎么處理的呢步悠?
來(lái)看下以下代碼:
console.log("a")
let r = new Promise(function (resolve, reject) {
console.log("b");
resolve()
});
r.then(() => console.log("c"));
setTimeout(() => { console.log("d") }, 0)
setTimeout(() => { console.log("e") }, 1000)
console.log("f")
如果不能在短時(shí)間得出準(zhǔn)確的結(jié)論,那么就需要深入了解js中的事件執(zhí)行機(jī)制了瘫镇。
宏任務(wù)和微任務(wù)
對(duì)于消息隊(duì)列中的任務(wù)鼎兽,分為兩類:
- 宏任務(wù)(macrotask ):setTimeout、setInterval
- 微任務(wù)(microtask):promise
宏任務(wù)中包含了微任務(wù)铣除,一個(gè)宏任務(wù)執(zhí)行完成谚咬,開(kāi)始下一個(gè)宏任務(wù)。
就拿上面代碼來(lái)說(shuō):
- 開(kāi)始執(zhí)行尚粘,發(fā)現(xiàn)了一些代碼择卦,放進(jìn)一個(gè)宏任務(wù)中
- 先執(zhí)行a
- 執(zhí)行b
- 發(fā)現(xiàn)異步操作then,屬于微任務(wù)郎嫁,把他添加進(jìn)當(dāng)前宏任務(wù)中的微任務(wù)的隊(duì)列
- 發(fā)現(xiàn)定時(shí)器d秉继,setTimeout屬于宏任務(wù),添加到宏任務(wù)的隊(duì)列
- 發(fā)現(xiàn)定時(shí)器e泽铛,setTimeout屬于宏任務(wù)尚辑,添加到宏任務(wù)的隊(duì)列
- 執(zhí)行f
- 代碼都已經(jīng)執(zhí)行完成,開(kāi)始執(zhí)行微任務(wù)隊(duì)列盔腔,打印出c
- 微任務(wù)隊(duì)列執(zhí)行完成杠茬,開(kāi)始執(zhí)行下一個(gè)宏任務(wù)隊(duì)列
- 直接打印出d月褥,沒(méi)有其他微任務(wù),開(kāi)始執(zhí)行下一個(gè)宏任務(wù)隊(duì)列
- 打印出e瓢喉,所有宏任務(wù)執(zhí)行完成