学习和理解宏任务和微任务

背景知识

  1. eventqueue 事件队列 --队是先进先出(买票排队)
  2. eventloop 事件循环 – 不间断地看有没有需要执行的回调和能不能执行(轮询)
  3. js执行机制(有问题,请留言指出,谢谢):从上到下开始执行,同步代码一直往下走,异步代码放到队列当中,然后继续走同步,同步走完之后,然后是事件循环,走事件队列,执行满足条件的回调,并根据情况决定执行完成之后是否注销回调

举栗子

例子:这个就是像食堂打饭排队,一个窗口有一个阿姨,问窗前的同学打哪些菜,然后确定这个同学不需要这个窗口的别的菜了,就给下一位同学打菜(请不要自杠插队行为).
- 宏任务就是阿姨给排队同学打菜
- 微任务就是排到队伍的同学选择要打的菜
- 先排队再打菜,等前面的打完要的菜了,再为下一个打菜
- 在一个事件流程里面,先走宏任务,再走微任务,等这个流程中所有的微任务

代码演示

//这是错误的代码,主要验证当前微任务不走完是否会继续走下一个宏任务

console.log("食堂开门了");


//行为函数
function waitList(num = 1) {
    return new Promise(resolve => {
        console.log("第" + (num) + "位同学开始打饭了");
        //假设平均每个人立刻时间打饭,是很假的
        setTimeout(() => {
            console.log("第" + (num++) + "位同学打好饭了");
        });
        if (num < 10) {
            resolve();
        }
    }).then(() => waitList(num))
}
//第一位同学是不需要等待的,早起的鸟儿有虫吃
waitList();
//为了更形象
setTimeout(() => {
    console.log(1111111)
})
Promise.resolve().then(() => {
    console.log(2222222)
})

//食堂开门了
//第1位同学开始打饭了
//第1位同学开始打饭了
//2222222
//第1位同学开始打饭了 * n
//这是我单身23年手速ctrl+c 弄出来的0.0

可以看出来,setTimeout的回调都没有执行,一直在走的都是then的回调,从第三个和第四个可以看出了,先走了上面的then,然后走了下面的then,然后就一直走第三个then之后的then的…(…像极了俄罗斯套娃)
也就是说以then为代表的微任务是有自己的队列的,自己这个队列走完之后才会走setTimeout为代表的宏任务的队列,因为不停地套娃,像极了一个数组shift之后又push,然后length一直不为0,就一直死磕这个数组
总结:主线程可以看做是一个宏任务,宏任务完成之后,检查微任务队列,并执行可执行的队列,执行队列完成之后,检查宏任务队列,再检查微任务队列,进行事件循环

//这是正常的一个逻辑流程,一个人打完,下一个
//主要还是上面的错误代码验证事件循环的问题
console.log("食堂开门了");
//行为函数
function waitList(num = 1){
    return new Promise(resolve=>{
        console.log("第" + (num) + "位同学开始打饭了");
        //假设平均每个人需要3秒时间打饭,是很假的
        setTimeout(() => {
            console.log("第" + (num++) + "位同学打好饭了");
            if(num<10){
                resolve(num);
            }
        }, 3000);
    }).then(num=>waitList(num))
}
//第一位同学是不需要等待的,早起的鸟儿有虫吃
waitList();

代表

宏任务

I/O 输入输出流—cin/cout之后,我对输入输出已经产生很大的误解了…
setTimeout/setInterval --定时器
setImmediate --nodejs 立即执行函数
requestAnimationFrame --浏览器,动画函数

微任务

process.nextTick --nodejs 进程的下一刻,这是个大哥,最先执行的微任务系列
MutationObserver – 浏览器节点观察者
Promise.then catch finally — es6 Promise语法

面试题

//基础面试题
setTimeout(_ => console.log(1))

new Promise(resolve => {
  resolve()
  console.log(2)
}).then(_ => {
  console.log(3)
})

console.log(4)

解析:

  1. 遇到setTimeout ,注册回调函数到宏任务队列
  2. 执行完成Promise参数,将then回调注册到微任务队列
  3. 执行console.log(4)
  4. 主线程完成,检查微任务队列 执行console.log(3),当前微任务队列清空
  5. 开始下一轮宏任务 执行console.log(1),宏任务完成

疑问:
都没有之后.事件循环是否还是一直存在,还是两者都空了之后就停止了?

结果:
2
4
3
1


这篇文章断断续续写了3天,写到后来自己都写懵了…

你可能感兴趣的:(JS)