4.主线程不断重复第三步
setTimeout(function () { console.log(1); }); new Promise(function (resolve, reject) { console.log(2); resolve(3); }).then(function (val) { console.log(val); console.log(4); }); // 堆代码 duidaima.com //2 3 4 1按照JS的执行顺序是先执行主线程上的同步任务,当同步任务执行完毕,执行栈清空后,再去微任务队列里取微任务执行,当执行栈为空后,我们再去宏任务队列中取宏任务执行。那么我们从上往下看,首先setTimeout是个宏任务,那么我们把它推入到宏任务队列里,下面Promise的构造函数则属于同步任务,那么我们在控制台上打印出个2,resolve(3)我们会传递给then()方法里的回调,而.then()里面的函数属于微任务,则把其推入到微任务队列里,则得出2 3 4 1的结果。
setTimeout(function () { console.log(1); }); new Promise(function (resolve, reject) { console.log(2); resolve(3); }).then(function (val) { console.log(val); console.log(4); setTimeout(() => { console.log(5); }); }); //2 3 4 1 5
我们在.then()的回调函数中塞入了一个setTimeout宏任务,那么在本次事件循环中,我们会把该setTimeout放入宏任务队列中去,但是它的执行时机并不是本次事件循环,而是会把这个回调放在下一轮的事件回调里,也就是说该任务会被放在宏任务队列里等待执行,而放置的位置取决于它前面还有没有宏任务在排队。
总的来说,微任务解决了宏任务执行时机不可控的问题。
console.log("1"); //setTimeout1 setTimeout(function () { console.log("2"); new Promise(function (resolve) { console.log("3"); resolve(); }).then(function () { console.log("4"); }); //setTimeout2 setTimeout(function () { console.log("5"); new Promise(function (resolve) { console.log("6"); resolve(); }).then(function () { console.log("7"); }); }); console.log("14"); }); new Promise(function (resolve) { console.log("8"); resolve(); }).then(function () { console.log("9"); }); //setTimeout3 setTimeout(function () { console.log("10"); new Promise(function (resolve) { console.log("11"); resolve(); }).then(function () { console.log("12"); }); }); console.log("13");首先主线程上的同步代码执行顺序为1 8 13,把9塞入微任务队列里去,等主线程的执行栈空了执行9,将setTimeout1和setTimeout3塞入宏任务队列里去;先执行setTimeout1,从上到下执行2 3,遇到4塞入微任务队列里去,下面的setTimeout2塞入宏任务队列里去,执行14,这时候把微任务队列里的4放到执行栈里执行;下面再执行宏任务队列里的setTimeout3,打印出10 11后将12塞入微任务队列里等待执行,执行栈为空后打印12,最后宏任务队列里还有setTimeout2等待执行,打印结果为5 6 7。所以最终打印结果是1 8 13 9 2 3 14 4 10 11 12 5 6 7。