同步任务,异步任务,微任务,宏任务,事件循环(event Loop)(一天一个问题13)

一、同步任务与异步任务

1.javascript是一门单线程语言,同一个时间只能做一件事(单线程与javascript引擎有关)
2.javascript里边任务分为同步任务和异步任务
3.同步任务会在主线程上排队执行,只有前一个任务执行完毕,才能执行后一个任务。异步任务不进入主线程,进入”任务队列”里边,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

1.1异步任务

1、定时器都是异步操作(setTimeout,setInterval)
2、事件绑定都是异步操作(onclick)
3、AJAX中一般我们都采取异步操作(也可以同步)
4、回调函数可以理解为异步(不是严谨的异步操作)(callback)
剩下的都是同步处理

1.2js如何实现异步操作(event Loop)

event Loop(事件循环),解决javascript单线程的问题。
例如:一个请求需要很久才会返回,单线程会阻碍程序的执行,这时就需要事件循环来解决阻碍问题。
event Loop:主线程上的同步任务执行完成之后,会推一个可执行的异步任务到主线程上执行,执行完成之后。再推一个异步任务到主线程上去执行,这样一个循环执行异步任务。

二、异步任务分类(宏任务和微任务)

2.1宏任务

定时器
事件绑定
ajax
回调函数
Node中fs可以进行异步的I/O操作

2.2微任务

Promise(async/await) => Promise并不是完全的同步,在promise中是同步任务,执行resolve或者reject回调的时候,此时是异步操作,会先将then/catch等放到微任务队列。当主栈完成后,才会再去调用resolve/reject方法执行
process.nextTick (node中实现的api,把当前任务放到主栈最后执行,当主栈执行完,先执行nextTick,再到等待队列中找)

2.3宏任务与微任务的执行

当主线程上的同步任务执行完成之后,先清理所有的微任务,再执行一个宏任务,清理所有的微任务。再执行一个宏任务,再清理所有的微任务(循环)。

三、题目

3.1
setTimeout(function(){
	console.log('1');
});
new Promise(function(resolve){		    
	console.log('2');
	resolve();
}).then(function(){		    
	console.log('3');
}); 		
console.log('4');
解读:setTimeout是一个宏任务。
	  new Promise()是一个构造函数同步任务,执行console.log(2)
	  Promise().then()是一个微任务。
	  执行console.log(4)。
	  同步任务执行完成,执行所有的微任务console.log(2)
	  所有的微任务执行完成,执行一个同步任务console.log(1)。
输出:2,4,3,1
3.2
setTimeout(()=>{
  new Promise(resolve =>{
  	resolve();
  }).then(()=>{
  	console.log('test');
  });

  console.log(4);
});

new Promise(resolve => {
  resolve();
  console.log(1)
}).then( () => {
  console.log(3);
  Promise.resolve().then(() => {
    console.log('before timeout');
  }).then(() => {
    Promise.resolve().then(() => {
      console.log('also before timeout')
    })
  })
})
console.log(2);

解读:
1.遇到setTimeout,异步宏任务,将() => {console.log(4)}放入宏任务队列中;
2.遇到new Promise,new Promise在实例化的过程中所执行的代码都是同步进行的,所以输出1;
3.而Promise.then中注册的回调才是异步执行的,将其放入微任务队列中
遇到同步任务console.log(2),输出2;
3.主线程中同步任务执行完从微任务队列中取出任务到主线程中,输出3,此微任务中又有微任务,Promise.resolve().then(微任务a).then(微任务b),将其依次放入微任务队列中;
从微任务队列中取出任务a到主线程中,输出 before timeout;
从微任务队列中取出任务b到主线程中,任务b又注册了一个微任务c,放入微任务队列中;
从微任务队列中取出任务c到主线程中,输出 also before timeout;微任务队列为空
4.从宏任务队列中取出任务到主线程,此任务中注册了一个微任务d,将其放入微任务队列中,接下来遇到输出4,宏任务队列为空
5.从微任务队列中取出任务d到主线程 ,输出test,微任务队列为空,结束~
3.3
console.log('1')
      setTimeout(()=>{
          console.log('2');
          new Promise(resolve=>{
            console.log('3')
            resolve();
          }).then(()=>{
            console.log('4')
          })
      },0)
      new Promise(resolve=>{
            console.log('5')
            resolve();
          }).then(()=>{
            console.log('6')
          }) 
      setTimeout(()=>{
          console.log('7');
      },0)   
      setTimeout(()=>{
          console.log('8');
          new Promise(resolve=>{
            console.log('9')
            resolve();
          }).then(()=>{
            console.log('10')
          })
      },0)
      new Promise(resolve=>{
            console.log('11')
            resolve();
          }).then(()=>{
            console.log('12')
          })
      console.log('13');
//1,5,11,13,6,12,2,3,4,7,8,9,10

博客地址

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值