事件循环的原理

150 阅读2分钟

事件循环的原因: js的本职工作是为了处理dom元素,因此不能是一个多线程的语言,例如这个操作删除了某个dom元素,而其他操作正在移动这个元素,会造成一些不可预见的问题,因此js从开始就是一个单线程语言。

所以对于一个代码块来说,js会优先处理其中的同步代码,那么异步代码应该怎么处理。 这里就涉及到了js的事件循环机制。当一个代码块遇到异步代码的时候,js会把异步的回调放到一个队列中,俗称任务队列。 当这部分的同步代码结束的时候,js会返回来处理任务队列的完成的异步函数。

    setTimeout(() => {
        console.log('setTimeout')
    }, 0);
    console.log(1)

针对上述代码,即使延时器的时间为0,但是由于先执行代码块中的同步代码,那么还是先打印1

1

setTimeout

我们除了setTimeout之外,还有promise会经常在工作中用到,那么promise既然是异步操作,他的代码顺序应该也是在后面了,我 们尝试一下

    var promiseT = new Promise((resove, reject) => {
        console.log('Promise')//直接执行
    })
    setTimeout(() => {
        console.log('setTimeout')
    }, 0);
    console.log(1)

我们会发现,打印的是

Promise

1

setTimeout

这是因为对于promise来说构造函数是同步执行的,所以会立即打印console.log('Promise'),但是 Promise中的回调函数是异步的,

var promiseT = new Promise((resove, reject) => {
    console.log('Promise')
    resove('resove')
})

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

console.log(1)

promiseT.then(res=>{
    console.log(res)
})

打印结果

Promise

1

resove

setTimeout

为什么明明setTimeout在代码块的前面,promise在后面,却先打印promise的回调呢

这是因为在js中对异步的执行分优先级,即我们说的宏任务微任务,对于一个事件队列中的异步任务,js会优先处理微任务,这也是为什么promiseT在后面却先执行的原因,对于宏任务和微任务的不同,这里不做阐述

下一期我会写一下时间循环在vue nexttick中的实际应用。 有什么更好的理解或者我有错的地方,大家指出来谢谢