js中的事件循环机制(宏任务和微任务都有哪些)

js事件循环机制

主线程(javascript引擎的线程)在运行过程中会产生一个东西叫做执行栈。而执行栈中,存在两个东西,一个叫堆,一个叫栈。堆里面存放着一些非结构化的数据或者是对象的内存空间。栈里面则是当前需要执行的代码。这些执行代码调用各种 api (如:dom事件,ajax, setTimeout,Promise等)。并往任务队列中添加各种事件,待执行栈中代码执行完毕后,会依次取出任务队列中的数据放入到执行栈中继续执行

主线程运行时,会产生执行栈(执行栈可以理解为代码运行的容器),栈内代码执行过程中当遇到任务源时,将任务源中的回调函数加入到任务队列中
执行栈中的代码执行完毕后,会依次调用任务队列中的代码放入到执行栈中执行,如果反复循环。就形成了我们所说的事件循环 Event loop

同步异步代码执行流程

1、在同一轮事件循环当中,同步任务会直接放入到主线程的执行栈进行执行,而异步任务不进入执行栈,而是进入任务队列中

2、同步任务按顺序执行,执行完毕后,才会去读取队列中的可执行的异步任务,并将可执行的异步任务依次加入到执行栈中执行。如此反复循环

宏任务和微任务都有哪些⭐⭐⭐⭐⭐
宏任务:script、setTimeOut、setInterval、setImmediate
微任务:promise.then,process.nextTick、Object.observe、MutationObserver
注意:Promise是同步任务
6、宏任务和微任务都是怎样执行的⭐⭐⭐⭐⭐
执行宏任务script,
进入script后,所有的同步任务主线程执行
所有宏任务放入宏任务执行队列
所有微任务放入微任务执行队列
先清空微任务队列,
再取一个宏任务,执行,再清空微任务队列
依次循环

宏任务和微任务

宏任务(macrotask)

可以简单的理解为每次执行栈中执行的代码

宏任务在执行过程中可以创建宏任务,也可以创建微任务,创建的宏任务会加入到宏任务队列中,等待下一个循环执行。而创建的微任务会在本次宏任务中的代码全部执行完成以后立刻依次执行。故宏任务中创建的微任务不会影响当前宏任务的执行
当一个宏任务执行完以后,会读取微任务队列中的任务,并依次全部执行完微任务队列中的任务。当微任务队列中的任务全部执行完成后,算是一个完整的task执行完成。
浏览器为了能够使得JS内部task与DOM任务能够有序的执行,会在一个task执行结束后,在下一个 task 执行开始前,对页面进行重新渲染 。如此过程不断重复,便是我们所说的事件循环,Event loop
常见的宏任务: setTimeout, setInterval, requestAnimationFrame, I/O, script标签内代码,setImmediate (Node环境中) 等(这些也被称作任务源)

微任务(microtask)

可以简单的理解为当前宏任务执行完成后立刻被执行的任务

微任务执行期在 本次宏任务执行完之后,下个宏任务执行之前,并且在UI渲染之前
微任务中创建的宏任务,也会被加入宏任务队列中,等待依次执行
微任务中创建的微任务,会在当前task中执行完成,也就是说微任务中创建的微任务,会在下一个宏任务执行前以及UI渲染前被执行
常见的微任务有: Promise callback, process.nextTick(node环境中),MutationObserver (这些也被称作任务源)
事件循环流程总结
1.、主线程开始执行一段代码, 假设开始执行一个 script 标签内的代码,将代码放入执行栈中执行,同步代码优先执行,执行过程中,当遇到任务源时,判断是宏任务还是微任务
2、 如果是宏任务,加入到宏任务队列中,如果是微任务,加入到微任务队列中
3、 同步代码执行完成,执行栈空闲,检查微任务队列中是否有可执行任务,如果有,依次执行所有微任务队列中的任务。如果没有。当前任务执行结束。
4、 渲染UI
5、 检查宏任务队列是否有可执行的宏任务,如果有,取出队列中最前面的那个宏任务,加入到执行栈中开始执行,然后重复 步骤1- 5。直到宏任务队列中所有任务执行结束

<script>
console.log('start');
 
setTimeout(() => {
    console.log('timeout');
}, 0);

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

console.log('end');
</script>
//star   end  promise   timeout

分析:

1、主线程开始执行,script 标签中的代码被加入到执行栈中执行,同步代码优先执行,依次输出 start => end
2、执行过程中,碰到任务源 setTimeout ,将 setTimeout 的回调函数加入到宏任务队列中
3、继续执行, 碰到任务源 promise, 将 promise 的回调函数加入到微任务队列中
4、end 输出后 执行栈空闲,检查微务队列,发现有一个微任务,取出进入到执行栈中执行,输出 promise
5、微任务队列中所有微任务执行完成,开始下一个循环
6、检查宏任务队列中是否有可执行的宏任务,发现有一个,取出放入执行栈中执行,输出 timeout
7、执行完毕

在做一道题:

   setTimeout(() => {
        console.log(1) // / 宏任务
      })
      new Promise((resolve) => {
        setTimeout(() => {
          console.log(2) // 宏任务
        })
        console.log(3) // 同步
        resolve()
      }).then(() => {
        setTimeout(() => {
          console.log(4) // 宏任务
        })
        console.log(5) // 微任务
      })
      console.log(6) // 同步
      //  3,6,5,1,2,4

做完这道题就无敌了

 // 宏任务与微任务
    setTimeout(() => {
      console.log('1');
      new Promise(function (resolve, reject) {
        console.log('2');
        setTimeout(() => {
          console.log('3');
        }, 0);
        resolve();
      }).then(function () {
        console.log('4')
      })
    }, 0);
    console.log('5'); //5 7 10 8 1 2 4 6 3
    setTimeout(() => {
      console.log('6');
    }, 0);
    new Promise(function (resolve, reject) {
      console.log('7');
      // reject();
      resolve();
    }).then(function () {
      console.log('8')
    }).catch(function () {
      console.log('9')
    })
    console.log('10');

     // 结果: 5,7, 10,8。  1,2,4,6,3

参考链接:js中的事件循环机制
深入剖析javascript的事件循环机制 Event loop

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值