js中事件循环之宏任务和微任务

首先我们看一个例子:

		console.log("a");

        setTimeout(()=>{
            console.log("b");
        },0);

        console.log("c");

        Promise.resolve().then(()=>{
            console.log("d");
        }).then(()=>{
            console.log("e");
        });

        console.log("f");

结果:acfdeb

JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。

Js先执行同步任务,遇到异步任务先放入任务队列,同步任务执行完后从任务队列里面取出异步任务。放到主线程执行

事件循环:主线程从任务队列中读取事件的过程是循环不断的,所以称为事件循环
在这里插入图片描述
事件循环执行过程:

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

异步任务

  • 宏任务(macrotask):每次执行栈执栈的代码(包括每次从事件队列中获取一个事件回调并放在执行栈中执行),包括主代码块(同步)、setTimeout、setInterval(异步)等
  • 微任务(microtask):微任务,在task执行结束后立即执行的任务,包括promise的then、process.nextTick(微任务队列,优先级更高)等

在这里插入图片描述
运行机制:

先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。

这么看来。文章开头的例子就很清楚明了了。

再来一个例子:

		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);

输出结果为:
在这里插入图片描述

  • 遇到setTimeout,异步宏任务,将() => {console.log(4)}放入宏任务队列中;
  • 遇到new Promise,new Promise在实例化的过程中所执行的代码都是同步进行的,所以输出1;
  • 而Promise.then中注册的回调才是异步执行的,将其放入微任务队列中
  • 遇到同步任务console.log(2),输出2;主线程中同步任务执行完
  • 从微任务队列中取出任务到主线程中,输出3,此微任务中又有微任务,Promise.resolve().then(微任务a).then(微任务b),将其依次放入微任务队列中;
  • 从微任务队列中取出任务a到主线程中,输出 before timeout;
  • 从微任务队列中取出任务b到主线程中,任务b又注册了一个微任务c,放入微任务队列中;
  • 从微任务队列中取出任务c到主线程中,输出 also before timeout;微任务队列为空
  • 从宏任务队列中取出任务到主线程,此任务中注册了一个微任务d,将其放入微任务队列中,接下来遇到输出4,宏任务队列为空
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值