async/await的执行顺序以及宏任务和微任务
一、async
带async关键字的函数,是声明异步函数,返回值是对象,如果async关键字函数返回的不是promise,会自动用Promise.resolve()包装。
返回值为 Promise {<resolved>: "test"}。
二、await
await等待右侧表达式的结果,这个结果是promise对象或者其他值。
如果它等到的不是一个 promise 对象,那 await 表达式的运算结果就是它等到的东西。
如果它等到的是一个 promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。
由于test()造成的阻塞,console.log(end)会等到两秒后执行
所以为了避免造成阻塞,await 必须用在 async 函数中,async 函数调用不会造成阻塞。
三、async/await的执行顺序
遇到await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,继续执行await后面的代码。(好好理解一下上面的说明。也就是说,await只会阻塞当前async方法内的代码,不会影响外部代码的执行)
执行结果:
首先执行宏任务,执行test1函数,执行console.log(statr test1)
· 遇到await,先执行右边test2中的console.log(test2),中断了后面的代码,执行test1外面的同步代码
· 执行console.log(start async);
· 遇到setTimeout,推到到下个宏任务队列中
· 执行Promise里面的同步代码console.log(promise1)
· 运行到promise().then,发现是promise对象,推到微任务队列中
· 执行console.log(end async)
· test1外面的同步代码执行结束后,回到test1中,console.log(await test2())执行完成后返回Promise {<resolved>: "return test2 value"},是promise对象,推到微任务队列中
· 此时第一个宏任务结束,执行所有的微任务,因为微任务队列先进先出,所以先执行console.log(promise2),后执行console.log(return test2 value)
· 执行test2完成后,后面的代码不再阻塞,执行console.log(end test1);
· 执行下个宏任务,即执行console.log(setTimeout);
四、常见的宏任务和微任务
宏任务:script、setTimeOut、setInterval、setImmediate
微任务: promise.then,process.nextTick、Object.observe、MutationObserver
注意:Promise是同步任务
宏任务和微任务的执行顺序:
-
执行宏任务script, 进入script后,所有的同步任务主线程执行 所有宏任务放入宏任务执行队列 所有微任务放入微任务执行队列 先清空微任务队列, 再取一个宏任务,执行,再清空微任务队列 依次循环
