对事件循环机制的一点记录

111 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

事件循环是什么?

就是一个执行任务队列的机制。

你了解浏览器的事件循环吗?为什么js在浏览器中有事件循环的机制?

JavaScript从诞生就是单线程。但是单线程就导致有很多任务需要排队,只有一个任务执行完才能执行后一个任务。如果某个执行时间太长,就容易造成阻塞,通过 Event loop 这个概念实现了非阻塞的操作

js是单线程的,(为什么js是单线程的),举个例子,如果有多个线程,一个线程删除了 DOM ,另一个线程要操作这个 DOM ,就会冲突,当然不只是这一种原因,为了避免这些问题,js是单线程的。

两种任务

宏任务:script代码块(整体代码块), setTImeout, setInterval, node 的 I/O 操作

微任务:new Promise().then, MutaionObserver(前端的回溯)

为什么有两种任务类型,只有宏任务不行吗

js代码执行过程中或者页面渲染过程中,宏任务都是保持着先进先出的原则,任务队列都是排队执行的,如果现在往任务队列里添加了一个事件,而且这个事件优先级非常高,需要立即执行,但因为宏任务的执行顺序,它肯定是最后执行的。所以只有宏任务是不可以的,引入了微任务的概念,处理一些优先级比较高的任务。

任务执行顺序

宏任务 ---> 微任务队列(如果在微任务中又碰到了微任务,会把微任务执行完毕) ---> 下一个宏任务

Node的事件循环和浏览器的事件循环有什么区别?

node宏任务

1.timers定时器 :已经进入任务队列的 setTimeout 和 setInterval 的回调函数

2.pending callback 待定回调:执行延迟到下一个循环迭代的 I/O 回调

3.idle,prepare:进系统内部使用

4.poll:检索新的 I/O 事件,执行与 I/O 相关的回调

5.check:执行 setImmediate 的回调函数

6.close callback:关闭事件,执行 socket.on('close', () => {}) 的回调

微任务和宏任务在node中的执行顺序 区别于版本(Node V10)

Node V10及以前:
  • 执行完一类宏任务中的所有任务,按上面的宏任务分类
  • 执行nextTick队列里的任务
  • 执行所有微任务
Node V10及以后
  • 和浏览器一致

输出顺序面试题

async function async1() {
    console.log("async1 start");
    await async2();
    console.log("async1 end");
}
async function async2() {
    console.log("async2");
}
console.log("script start");
setTimeout(function () {
    console.log("setTimeout");
}, 0);
async1();
new Promise(function (resolve) {
    console.log("promise");
    resolve();
}).then(function () {
    console.log("promise2");
});
console.log("script end"); 
console.log("start");
setTimeout(() => {
    console.log("1");
    Promise.resolve().then(() => {
        console.log("2");
    });
}, 0);
new Promise(function (resolve) {
    console.log("3");
    setTimeout(() => {
        console.log("4");
        resolve("5");
    }, 0);
}).then((res) => {
    console.log("6");
    setTimeout(() => {
        console.log(res);
    }, 0);
})
const p = function () {
    return new Promise((resolve, reject) => {
        const p1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("1")
            }, 0);
            resolve("2");
        });
        p1.then((res) => {
            console.log(res);
        })
        console.log("3");
        resolve("4");
    });
}
​
p().then((res) => {
    console.log(res);
})
console.log("end");
setTimeout(() => {
    console.log("setTimeout宏任务")
}, 0);
​
let test = async () =>{
    console.log("promise 同步代码1")
    let onePromise = await new Promise((resolve, reject) => {
        resolve("success")
    });
    console.log("promise微任务执行2");
}
​
test();
​
new Promise((resolve, reject) => {
    console.log("promise 同步代码")
    resolve("success");
}).then((data) => {
    console.log("promise微任务执行1")
})
console.log("end");
async function test() {
    console.log("async1");
    await new Promise((resolve, reject) => {
        resolve(1)
    });
    console.log('async2');
};
setTimeout(function () {
    console.log("setTimeout");
}, 0);
test();
new Promise(function (resolve) {
    console.log("promise1");
    resolve();
}).then(function () {
    console.log("promise2");
});
console.log('end');