事件循环理解
由来
JS的本质是单线:
-
一般来说,非阻塞性的任务采取同步的方式,直接在主线程的执行栈完成。
-
一般来说,阻塞性的任务都会采用异步来执行,异步的工作一般会交给其他线程完成,然后回调函数会放到事件队列中。
执行顺序
-
[宏任务:macro task]
-
定时器
-
事件绑定
-
ajax
-
回调函数
-
Node中fs可以进行异步的I/O操作
-
-
[微任务:micro task]
-
Promise(async/await) => Promise并不是完全的同步,当在Excutor中执行resolve或者reject的时候,此时是异步操作,会先执行then/catch等,当主栈完成后,才会再去调用resolve/reject把存放的方法执行
-
process.nextTick (node中实现的api,把当前任务放到主栈最后执行,当主栈执行完,先执行nextTick,再到等待队列中找)
-
MutationObserver (创建并返回一个新的 MutationObserver 它会在指定的DOM发生变化时被调用。)
-
任务队列到达时间后先进先出的原则
这里我省略了同步任务,空白就相当于是同步任务,红色代表宏任务,蓝色代表微任务
console.log(1);
document.addEventListener("14", function () {
console.log(14);
});
new Promise(function (resolve) {
resolve();
console.log(2);
setTimeout(function () {
console.log(3);
}, 0);
Promise.resolve().then(function () {
console.log(4);
setTimeout(function () {
console.log(5);
}, 0);
setTimeout(function () {
(async function () {
console.log(6);
return function () {
console.log(7);
};
})().then(function (fn) {
console.log(8);
fn();
});
}, 0);
});
new Promise(function (resolve) {
console.log(9);
resolve();
}).then(function () {
new Promise(function (resolve, reject) {
console.log(10);
reject();
})
.then(function () {
setTimeout(function () {
console.log(11);
}, 0);
console.log(12);
})
.catch(function () {
console.log(13);
var evt = new Event("14");
document.dispatchEvent(evt);
});
});
});
setTimeout(function () {
console.log(15);
Promise.resolve().then(function () {
console.log(16);
});
}, 0);
//答案是1 2 9 4 10 13 14 3 15 16 5 6 8 7
首先侦听事件是在等待后的同步任务
第二个是在reject的时候会被catch捕获不会进入then之后的代码
第三个就是在参数fn执行了之后才会返回return的 7