單線程,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í)行打印操作,并不是真實的300ms,那么就能猜到原理了吧,就是一個主線程隊列和異步線程隊列唄,先執(zhí)行完主線程隊列,才輪的上異步線程隊列執(zhí)行啊。
另外,setTimeout的的最低延遲是4ms,所以設(shè)置為0也是騙人的。
另外setInterval同理,也是每隔一段時間會往異步線程里面推一下。
把代碼王五抬上來:
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
為啥呢?
其實js除了同步任務(wù)和異步任務(wù),還細(xì)分為宏任務(wù)和微任務(wù);
- macro-task(宏任務(wù)):包括整體代碼script,setTimeout,setInterval
- micro-task(微任務(wù)):Promise,process.nextTick
然后我們分析一下代碼王五;
代碼開始執(zhí)行,整體就是一個宏任務(wù),遇到了setTimeout 發(fā)現(xiàn)這玩意是一個異步任務(wù),而且是宏任務(wù),先丟一邊兒,然后遇到了一個promise,發(fā)現(xiàn)這玩意是個當(dāng)前宏任務(wù)下的一個微任務(wù),然后就執(zhí)行了一下console.log('promise'),然后就丟到一邊去,然后遇到了一個console.log('console'); 截止到目前為止,共打印了promise和console,然后開始執(zhí)行本次的微任務(wù),即then,然后執(zhí)行異步隊列的宏任務(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')
})
})
這段代碼就有點兒牛逼了啊,這玩意是啥?。?br> 讓我們一點點兒分析哈。
首先代碼們開始執(zhí)行,即宏任務(wù)開始,打印 【1】,遇到了setTimeout丟到異步隊列里面,然后遇到了process.nextTick(當(dāng)前隊列的微任務(wù)),然后遇到了Promise,打印【7】,丟到微任務(wù)隊列里,然后遇到了
setTimeout,丟到異步隊列里面去,然后開始執(zhí)行本次的微任務(wù),打印【6】和【8】,第一次執(zhí)行完了,打印了【1】【7】【6】【8】
接下來分析異步隊列啦~
首先第一個timeout打印一個【2】,然后遇到了兩個微任務(wù),先打印【4】,然后開始執(zhí)行微任務(wù),打印【3】和【5】 到此為止,第一個異步任務(wù)的全部執(zhí)行完了,現(xiàn)在打印的結(jié)果是【1】【7】【6】【8】【2】【4】【3】【5】,然后開始執(zhí)行下面的timeout,結(jié)果和第一個類似,所以最終的打印結(jié)果是:
【1】【7】【6】【8】【2】【4】【3】【5】【9】【11】【10】【12】
看到這里,應(yīng)該對js的同步,異步,宏任務(wù),微任務(wù)了如指掌了吧,那么開始你的編程之旅吧!