單線程玖翅,eventLoop 這是關(guān)鍵字,其他都是浮云割以。
眾所周知金度,javascript是單線程的,也就是說干活的就一條主線程拳球,那么異步是怎么回事呢审姓?
把代碼張三抬上來:
setTimeout(() => {
console.log('timeout');
},300)珍特;
console.log('main process')
99%的前端從業(yè)者都知道先打印main process 后打印timeout祝峻,再次也不必多啰嗦了。
把代碼李四抬上來:
setTimeout(() => {
console.log('timeout');
},300)扎筒;
sleep(2000);
假設(shè)下面的同步操作執(zhí)行了2000ms莱找,那么timeout會在大于2000ms后才執(zhí)行打印操作,并不是真實(shí)的300ms嗜桌,那么就能猜到原理了吧奥溺,就是一個(gè)主線程隊(duì)列和異步線程隊(duì)列唄,先執(zhí)行完主線程隊(duì)列骨宠,才輪的上異步線程隊(duì)列執(zhí)行啊浮定。
另外相满,setTimeout的的最低延遲是4ms,所以設(shè)置為0也是騙人的桦卒。
另外setInterval同理立美,也是每隔一段時(shí)間會往異步線程里面推一下。
把代碼王五抬上來:
setTimeout(function() {
console.log('setTimeout');
})
new Promise(function(resolve) {
console.log('promise');
resolve();
}).then(function() {
console.log('then');
})
console.log('console');
如何打印呢?答案是promise方灾,console建蹄,then,setTimeout
為啥呢裕偿?
其實(shí)js除了同步任務(wù)和異步任務(wù)洞慎,還細(xì)分為宏任務(wù)和微任務(wù);
- macro-task(宏任務(wù)):包括整體代碼script嘿棘,setTimeout劲腿,setInterval
- micro-task(微任務(wù)):Promise,process.nextTick
然后我們分析一下代碼王五蔫巩;
代碼開始執(zhí)行谆棱,整體就是一個(gè)宏任務(wù),遇到了setTimeout 發(fā)現(xiàn)這玩意是一個(gè)異步任務(wù)圆仔,而且是宏任務(wù)垃瞧,先丟一邊兒,然后遇到了一個(gè)promise坪郭,發(fā)現(xiàn)這玩意是個(gè)當(dāng)前宏任務(wù)下的一個(gè)微任務(wù)个从,然后就執(zhí)行了一下console.log('promise'),然后就丟到一邊去歪沃,然后遇到了一個(gè)console.log('console'); 截止到目前為止嗦锐,共打印了promise和console,然后開始執(zhí)行本次的微任務(wù)沪曙,即then奕污,然后執(zhí)行異步隊(duì)列的宏任務(wù),就是setTimeout液走,所以打印順序就是這樣滴碳默。
把代碼趙六抬上來:
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
這段代碼就有點(diǎn)兒牛逼了啊,這玩意是啥霸悼簟嘱根?
讓我們一點(diǎn)點(diǎn)兒分析哈。
首先代碼們開始執(zhí)行巷懈,即宏任務(wù)開始该抒,打印 【1】,遇到了setTimeout丟到異步隊(duì)列里面顶燕,然后遇到了process.nextTick(當(dāng)前隊(duì)列的微任務(wù))凑保,然后遇到了Promise冈爹,打印【7】,丟到微任務(wù)隊(duì)列里欧引,然后遇到了
setTimeout犯助,丟到異步隊(duì)列里面去,然后開始執(zhí)行本次的微任務(wù)维咸,打印【6】和【8】剂买,第一次執(zhí)行完了,打印了【1】【7】【6】【8】
接下來分析異步隊(duì)列啦~
首先第一個(gè)timeout打印一個(gè)【2】癌蓖,然后遇到了兩個(gè)微任務(wù)瞬哼,先打印【4】,然后開始執(zhí)行微任務(wù)租副,打印【3】和【5】 到此為止坐慰,第一個(gè)異步任務(wù)的全部執(zhí)行完了,現(xiàn)在打印的結(jié)果是【1】【7】【6】【8】【2】【4】【3】【5】用僧,然后開始執(zhí)行下面的timeout结胀,結(jié)果和第一個(gè)類似,所以最終的打印結(jié)果是:
【1】【7】【6】【8】【2】【4】【3】【5】【9】【11】【10】【12】
看到這里责循,應(yīng)該對js的同步糟港,異步,宏任務(wù)院仿,微任務(wù)了如指掌了吧秸抚,那么開始你的編程之旅吧!