js异步之宏任务(marcroTask)和微任务(microTask)

   日期:2020-10-08     浏览:160    评论:0    
核心提示:先看一到面试题写出console.log的输出顺序console.log(100);setTimeout(()=>{ console.log(200);})setTimeout(()=>{ console.log(201);})Promise.resolve().then(()=>{ console.log(300);})console.log(400);// 100 400 300 200 201// 为什么300比200

先看一到面试题

写出console.log的输出顺序

console.log(100);

setTimeout(()=>{ 
    console.log(200);
})


setTimeout(()=>{ 
    console.log(201);
})


Promise.resolve().then(()=>{ 
    console.log(300);
})

console.log(400);


// 100 400 300 200 201


// 为什么300比200先打印

为什么300比200先打印这里就引出了宏任务和微任务????

什么是宏任务和微任务

宏任务包括:setTimeout setInterval Ajax DOM事件
微任务:Promise async/await
微任务比宏任务的执行时间要早

同步异步问题

首先,你要知道javascript是单线程语言。js任务需要排队顺序执行,如果一个任务耗时过长,后边一个任务也的等着,但是,假如我们需要浏览新闻,但新闻包含的超清图片加载很慢,总不能网页一直卡着直到图片完全出来,所以将任务设计成了两类:

同步任务
异步任务

当我们打开网站时,网页的渲染过程就是一大堆同步任务,像页面骨架和页面元素的渲染,而加载图片、音乐之类的任务就是异步任务,看一下下边导图:


同步和异步任务分别进入不同的执行“场所”,同步进入主线程,异步进入Event Table并注册函数。当指定的事情完成时,Event Table会将这个函数移入Event Queue。主线程内的任务执行完毕为空,回去了Event Queue读取对应的函数,进入主线程。

上述过程会不断重复,也就是常说的Event Loop(事件循环)。

但是,JS异步还有一个机制,就是遇到宏任务,先执行宏任务,将宏任务放入event queue,然后再执行微任务,将微任务放入micro task queue,但是,这两个queue不是一个queue。当你往外拿的时候先从微任务里拿这个回调函数,然后再从宏任务的queue拿宏任务的回调函数,如下图:



所以最终的执行步骤为:

先是将所有同步代码执行完毕后,call back(任务栈)清空
然后执行当前的微任务
然后执行当前的宏任务
再尝试DOM的渲染
最后触发Event Loop

三、执行顺序

1.主线程上宏任务、微任务执行顺序

console.log('---start---');//第一轮主线程
 
setTimeout(() => { 
  console.log('setTimeout');  // 将回调代码放入个宏任务队列,第二轮宏任务执行
}, 0);
 
new Promise((resolve, reject) => { 
  console.log('---Promise第一轮微任务同步执行---');//第一轮微任务同步执行
  resolve()
}).then(()=>{ 
  console.log('Promise.then实例成功回调执行'); // 将回调代码放入微任务队列,第一轮宏任务执行完后立即执行
});
 
console.log('---end---');//第一轮主线程结束

执行顺序:主线程 >> 主线程上创建的微任务 >> 主线程上创建的宏任务

2.宏任务中包含微任务

// 宏任务队列 1
setTimeout(() => { 
  // 宏任务队列 2.1
  console.log('timer_1');
  setTimeout(() => { 
    // 宏任务队列 3
    console.log('timer_3')
  }, 0)
  new Promise(resolve => { 
    resolve()
    console.log('new promise')
  }).then(() => { 
    // 微任务队列 1
    console.log('promise then')
  })
}, 0)
 
setTimeout(() => { 
  // 宏任务队列 2.2
  console.log('timer_2')
}, 0)
console.log('========== Sync queue ==========')

执行顺序:主线程 >> 主线程上的宏任务队列1 >> 宏任务队列1中创建的微任务

========== Sync queue ==========
 
1 timer_1
2 new promise
3 promise then
4 timer_2
5 timer_3

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服