众所周知,js是一门单线程的语言。主要同他的用途有关,同一个时间只能作一件事儿,做为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操做DOM,这决定了它只能是单线程,不然会带来很复杂的同步问题。java
因为javaScript的资源加载是按序进行的,javaScript的单线程决定只有一个任务结束才能够执行下一个任务,不然只能是下一个任务处于等待状态。而任务分为同步任务与异步任务:
同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务:不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务能够执行了,该任务才会进入主线程执行;
一般咱们会将网页的Dom渲染做为同步任务,将获取远程数据,图片加载等操做做为异步任务进行。面试
promise.Trick() > promise的回调 > async > setTimeout > setInterval
promise
宏任务:包括总体代码script,setTimeout,setInterval
微任务:Promise,process.nextTick浏览器
事件循环的顺序决定js代码的执行顺序,进入总体代码(宏任务)后,开始第一次循环。全部的同步任务先执行,根据任务类型部分异步任务进入入Event Queue,部分异步任务进入不一样的Event Queue,宏任务的第一次循环结束后接着执行全部的微任务。而后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行全部的微任务。bash
console.log('start')
async function async1() {
console.log("async1");
await async2();
console.log("async1");
}
async function async2() {
console.log( 'async2');
}
console.log("script");
setTimeout(function () {
console.log("setTimeout");
},0);
async1();
new Promise(function () {
console.log("promise1");
}).then(function () {
console.log("promise2");
});
复制代码
输出:异步
start
script
async1
async2
promise1
promise2
async1
setTimeout
复制代码
解析: 首先执行全部的同步任务,async与await搭配使用时是异步任务,async单独定义函数时则当作同步任务执行,因此输出start,script,遇到setTimeout将其放在入Event Queue任务队列中,执行async1函数后 输出async1,async2,此时要等待async2执行完毕,将其放在微任务的Event Queue中,因此此时主线程执行下面的代码,new Promise实例会当即执行,输出promise1,碰到then异步函数进入Event Queue任务队列中,此时宏任务第一轮执行完毕,去执行全部的微任务,微任务执行结束后将宏任务的任务队列的异步任务放在主线程进行执行。async