鍍金池/ 問(wèn)答/HTML/ Promise的then方法中的回調(diào)函數(shù)和setTimeout執(zhí)行順序問(wèn)題

Promise的then方法中的回調(diào)函數(shù)和setTimeout執(zhí)行順序問(wèn)題

  setTimeout(function(){
        console.log('D');
    },0)

    var promise = new Promise(function(resolve, reject){
        console.log('A');
        resolve('C');
    })

    console.log('B');
    
      promise.then(function(value){
        console.log(value)
    });
    
    這段代碼AB先打印我沒(méi)問(wèn)題,就是不理解為什么是C先于D打印,按理說(shuō)應(yīng)該是setTimeout先把回調(diào)放進(jìn)任務(wù)隊(duì)列里面等待執(zhí)行吧
回答
編輯回答
綰青絲

因?yàn)橛袀z個(gè)隊(duì)列.

一個(gè)是 microtask 隊(duì)列, 一個(gè) macrotask 隊(duì)列.

promise 是放入 microtask 隊(duì)列的, 而 setTimeout 放入 macrotask 隊(duì)列.

先處理 microtask 隊(duì)列, microtask 隊(duì)列每次處理直到隊(duì)列為空, 接下來(lái)處理 macrotask 隊(duì)列, macrotask 每次只處理的隊(duì)列里的第一個(gè)任務(wù), 當(dāng)任務(wù)處理完后, 又會(huì)進(jìn)入到 microtask 隊(duì)列的處理. 如此反復(fù).

2018年7月2日 08:27
編輯回答
純妹

這個(gè)很好理解,根本在于明確理解異步問(wèn)題。

首先關(guān)于setTimeout你的理解沒(méi)錯(cuò),是一個(gè)隊(duì)列執(zhí)行,這里類(lèi)似于setTimeout的還有很多,比如node中的:
setImmediate, process.nextTick等,都是類(lèi)似機(jī)制。
這些函數(shù)都是延時(shí)執(zhí)行,顧名思義就是要放進(jìn)隊(duì)列排隊(duì)的,哪怕設(shè)置了延時(shí)0.

但是 Promise是什么呢
簡(jiǎn)單說(shuō),不過(guò)是 一種 異步編程的解決方案,說(shuō)白了是改變之前 回調(diào)函數(shù)寫(xiě)法的 問(wèn)題。Promise,簡(jiǎn)單說(shuō)就是一個(gè)容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。而這個(gè)存儲(chǔ)的隊(duì)列是promsie本身維護(hù)的自己的隊(duì)列,千萬(wàn)不要和setTimeout的系統(tǒng)事件調(diào)度隊(duì)列混淆。

針對(duì)你的這個(gè)問(wèn)題,你這個(gè)promise沒(méi)有異步,所以promsie的狀態(tài)馬上就變成了 resolve的,所以呢,通過(guò)then注冊(cè)的回調(diào)函數(shù)馬上就會(huì)調(diào)用?;臼蔷褪峭綀?zhí)行而已。當(dāng)然比setTimeout先執(zhí)行。

2017年6月8日 03:00
編輯回答
野橘

這里涉及到異步的宏任務(wù)和微任務(wù),setTimeout是宏任務(wù),Promise整體是微任務(wù),主線(xiàn)程執(zhí)行完了之后先從微任務(wù)棧里面獲取微任務(wù)執(zhí)行,沒(méi)有微任務(wù)了,就去宏任務(wù)棧里面獲取宏任務(wù)執(zhí)行,所以在一個(gè)循環(huán)內(nèi),微任務(wù)是比宏任務(wù)先執(zhí)行的,所以先打印C再打印D

2018年3月6日 12:18