事件循环:
js事件分为宏任务和微任务,宏任务为script、setTimeout、setInterval;微任务为Promise.then,process.nextTick;
事件执行顺序是先执行宏任务,接着把所有微任务执行完,再次执行宏任务,以此循环。
任务分成同步任务和异步任务;
事件循环即:同步任务直接进入主线程里,异步任务先去事件列表里注册,然后回到消息队列里等待,同步事件执行完后,会读取事件列表里的异步任务放到主线程里执行
async function 声明将定义一个返回 AsyncFunction 对象的异步函数。
async 函数返回一个值时,Promise 的 resolve 方法会负责传递这个值;当 async 函数抛出异常时,Promise 的 reject 方法也会传递这个异常值。
await返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。
async返回的promise对象,遇到await会先返回,触发的异步函数先执行完毕后,再接着执行。
Promise虽然是个立即执行的函数,但resolve是异步执行的回调。所以,resolve()会被放到回调队列中,当执行到resolve()时,任务会被放入到消息队列中,等待调用栈有空闲时事件循环再来取走它。
记一道经典面试题:
async function async1 () { console.log('async1 start') await async2() console.log('async1 end') } async function async2 () { console.log('async2') } console.log('script start') setTimeout(function () { console.log('setTimeout') }, 0) async1(); new Promise(function (resolve) { console.log('promise1') resolve(); }).then(function () { console.log('promise2') }) console.log('script end')
首先肯定是打印script start,接着开始调用async1 函数,打印async1 start,进入async2函数,打印async2,完毕开启异步副本,Promise因为是立即执行,所以进入new Promise,打印promise1,resolve又是一个异步所以先进消息队列里等着,打印script end,执行完后relosve已经在等着了,打印promise2,异步结束,打印async1 end,因为setTimeout是宏任务,所以最后执行,打印setTimeout。
正确答案就是:
script start async1 start async2 promise1 script end promise2 async1 end setTimeout