1 setTimeout(()=> console.log("a"),0);//定时器 回调 2 var p=new Promise(resolve=>{ 3 //直接写在new Promise中的代码属于主程序,会立刻执行 4 console.log("b");//主程序 立刻执行 5 setTimeout(()=>console.log("f"),0);//定时器 回调 6 resolve();//自动调用.then()中的代码 7 }); 8 p.then(()=>console.log("c"));//微任务 回调 9 p.then(()=>console.log("d"));//微任务 回调 10 console.log("e");//主程序
例如setTimeout(()=>{...}),setInterval(()=>{...}),xhr.send()等语句都是异步调用语句,它们会创建对象,但暂不执行,(当定时器等待时间结束时,回调函数会自动执行,当Xhr.onreadystatechange(){...}相应结果回来时会自动执行,这些异步回调函数执行时都不能进入主程序执行,会先进入任务队列等待),当主程序执行完后,事件循环会将事件队列里的回调函数放到主程序执行,会按顺序执行,先进队列的回调函数先出队列。
但有一种特殊对象promise会直接放到主程序执行(直接写在new promise里的代码属于主程序会立刻执行,但写在里面的异步代码还是会异步执行),promise的then不会放到异步对象里执行,会放到微任务中,微任务是比一般函数更小的函数,事件循环会先碰见微任务,所以微任务会比ajax,定时器优先执行,resolve()会启动.then中的代码,虽然会立刻调用还是会排在主程序后,总结起来执行顺序为主程序、微任务、异步任务。
所以上面代码输出结果为
b e c d a f
还有一种更特殊的回调.nextTick,它也会放入微任务中执行,但又比.then优先级高,所以会比.then提前执行
process.nextTick(function(){console.log(7)}); new Promise(function(resolve){ console.log(3);//主程序 resolve(); console.log(4);//主程序 }).then(function(){ console.log(5); }) process.nextTick(function(){ console.log(8); })
//输出结果 3 4 7 8 5