美文网首页
一道关于js宏任务、微任务面试题引发的思考

一道关于js宏任务、微任务面试题引发的思考

作者: isSunny | 来源:发表于2019-07-18 15:27 被阅读0次

    先看面试题

    async function async1(){
        console.log('1')
        await async2()
        console.log('2')
    }
    async function async2(){
        console.log('3')
    }
    console.log('4')
    setTimeout(function(){
        console.log('5') 
    },0)  
    async1();
    new Promise(function(resolve){
        console.log('6')
        resolve();
    }).then(function(){
        console.log('7')
    })
    console.log('8')
    

    上面的题,答案是什么呢?
    答案是:4,1,3,6,8,2,7,5

    懵逼了吗?反正我第一次接触看到这个面试时候是一脸懵,好吧,继续说。
    javascript是单线程,所以只有唯一的事件循环,这个时候js就把所有任务分为了两种:同步任务和异步任务。
    而异步任务的两种分类分别为:宏任务和微任务。

    同步任务:就是在主线程上排队执行的任务,只有在前面的任务执行完后,才能执行后面的任务;

    异步任务:是指不进入主线程,而是进入“任务队列”的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

    事件循环EventLoop
    是JS的执行机制,是指同步任务进入主线程后,而异步任务进入Event Table注册函数,当异步事件完成后,会将回调函数放入Event Queue中,当同步任务完成后,会从Event Queue中读取事件放入主线程执行,这个过程不断循环执行。

    事件的执行顺序是先执行宏任务,然后执行微任务。微任务按先进先出的顺序执行;微任务清空后再执行宏任务,按先进先出的顺序取出执行。

    如下图:


    image.png
    image.png

    宏任务:包括整体代码script,setTimeout,setInterval
    微任务:Promise.then(非new Promise),process.nextTick(node中)

    下面我们就来看一下上面的结果是怎么得出来的吧!
    1.先打印4,这个就不说了;
    2.走到setTimeout,是一个宏任务,它要先等当前的宏任务结束后再执行;
    3.async1();执行该函数,先打印1,然后执行async2()函数,打印3,因为async2函数前面有await关键字,会隐式返回promise微任务,进入回调队列;
    4.执行new promise,同步任务,先打印6,后面.then()微任务进入回调队列;
    5.打印8,此时同步任务执行完毕,读取任务队列,进入主线程执行;
    6.还记得微任务先进先出的顺序吧,此时先执行async2返回的一个promise,打印2;
    7.接着到promise.then(),打印出7;
    8.到这里当前的宏任务结束,执行下一轮的宏任务setTimeout,所以最后打印出5;

    最终结果就是4.1.3.6.8.2.7.5

    再说一下函数前面多了一个aync关键字。
    await关键字只能用在aync定义的函数内,async函数会隐式地返回一个promise。
    

    相关文章

      网友评论

          本文标题:一道关于js宏任务、微任务面试题引发的思考

          本文链接:https://www.haomeiwen.com/subject/ywpklctx.html