步遥——事件循环队列

2020-12-06  本文已影响0人  你还想好吗

       js由于处理浏览器事件的原因,所以它是一个单线程的处理机制。但是为了提高cpu的利用率,js在主线程之外,会把一些计算的任务分配给子任务。事件循环就是js处理多任务同时进行的一种机制。

       js维护着一个调用栈,一个消息队列,一个微任务队列 ,其中调用栈中是同步任务代码,当执行过程中,遇到了同步任务,就压入调用栈中,并立即执行该任务,执行完毕之后,就把该执行环境销毁。当遇到一个异步任务,会根据是宏任务还是微任务,将该任务中的回调压入到对应的队列中。比如setTimeout,setInterval,setImmediate,I/O,UI rendering,等都是宏任务,遇到这些任务,会将这些方法中的回调中的处理任务(回调函数内部的代码)压入到消息队列中,而如果遇到了promise,process.nextTick,这样的微任务,就会把这些函数的回调函数放入到微任务队列中(new promise中的参数是同步任务,只有.then中的才是异步任务)。

       当调用栈中的代码执行完毕之后,就会先去检查微任务队列,如果微任务队列中有任务,就将微任务队列中待执行的全部任务依次压入调用栈中执行,直到微任务队列中的代码被执行完毕,然后去检查宏任务队列,再将宏任务队列中的第一个任务压入到调用栈中进行执行,执行完第一个宏任务之后,再去检查调用栈中是否有未执行的代码,优先执行调用栈中的代码,执行完毕之后再优先检查微任务队列,依次执行完所有的微任务队列中的代码后再去检查宏任务队列,还是只取出宏任务队列中的第一个任务执行,执行完毕之后,再去检查执行栈中是否有待执行任务,然后是微任务队列,最后再是宏任务队列,依次无限循环下去。。。

        举个例子:

var p = new Promise(resolve => {

    console.log(4);//同步先执行

    resolve(5)

    })

    function fun1(){

    console.log(1)

    }

    function fun2(){

    setTimeout(()=>{

    console.log(2)

    });

    fun1();

    console.log(3);

    p.then(resolved=>{

    console.log(resolved)

    }).then(()=>{

    console.log(6)

    })

    }

setTimeout(() => {

    console.log(7)//宏任务先压入宏任务队列

}, 0);

    fun2()//执行func2时又压入一个宏任务和2个微任务

    fun1()//同步任务,要优于以上两个宏任务和微任务,但是2个微任务的执行优先级高于2个宏任务

输出:

4

1

3

1

5

6

7

2

        这就是js中的事件循环机制。了解了该循环处理事件的机制,就能很好的遇见代码的执行顺序,并再出现问题时根据执行的顺序定位对应的问题点。

上一篇下一篇

猜你喜欢

热点阅读