执行顺序:先执行同步代码,遇到异步代码就先加入队列,然后按入队顺序执行异步代码,最后执行setTimeout队列的代码
setTimeout的任务队列优先级低于promise队列,setTimeout的队列与promise不是一个队列
例子
setTimeout(function(){ console.log('2'); },0); let promise = new Promise(function(resolve, reject) { console.log('3'); resolve(); }).then(function(){ console.log('resolve3'); }).then(function(){ console.log('reject3') }); console.log('4');
执行结果是:3,4,resolve3,reject3,2
从规范上来讲,setTimeout有一个4ms的最短时间,也就是说不管你设定多少,反正最少都要间隔4ms才运行里面的回调。而Promise的异步没有这个问题。
创建Promise实例是同步执行的,所以会先输出3,4
promise.then与setTimeout都是异步执行的,会先执行promise.then
例:
async function async1() { console.log("async1 start"); //(2) await async2(); console.log("async1 end"); //(7) } async function async2() { console.log( 'async2'); //(3) } console.log("script start"); //(1) setTimeout(function () { console.log("settimeout"); //(8) },0); async1(); new Promise(function (resolve) { console.log("promise1"); //(4) resolve(); }).then(function () { console.log("promise2"); //(6) }); console.log('script end');//(5)
先按顺序执行同步代码 从‘script start‘开始,
执行到setTimeout函数时,将其回调函数加入队列(此队列与promise队列不是同一个队列,执行的优先级低于promise)。
然后调用async1()方法,await async2();//执行这一句后,输出async2后,await会让出当前线程,将后面的代码加到任务队列中,然后继续执行test()函数后面的同步代码
继续执行创建promise对象里面的代码属于同步代码,promise的异步性体现在then与catch处,所以promise1被输出,然后将then函数的代码加入队列,继续执行同步代码,输出script end。至此同步代码执行完毕。
开始从队列中调取任务执行,由于刚刚提到过,setTimeout的任务队列优先级低于promise队列,所以首先执行promise队列的第一个任务,因为在async函数中有await表达式,会使async函数暂停执行,等待表达式中的 Promise 解析完成后继续执行 async 函数并返回解决结果。
所以先执行then方法的部分,输出promise2,然后执行async1中await后面的代码,输出async1 end。。最后promise队列中任务执行完毕,再执行setTimeout的任务队列,输出settimeout。
setTimeout(fn,0)的含义是指某个任务在主线程最早可得的空闲时间执行。它在“任务队列”的尾部添加一个事件,因此要等到同步任务和“任务队列”现有的时间处理完才会得到执行。