本文是我自己对事件循环的理解和总结,不会有太多的理论知识,已经有太多文章写过了,自己搜索下就能找到很多;
同时,文章中的观点仅是本人自己理解,比较白话,不用太较真啊!
事件是特定情况下触发的操作。这里的操作是用函数封装起来的,所以,事件就是在特定情况下触发的函数。
例如:
上面的这些情况的回调函数,都是在特定情况下触发的函数,所以都可以称为事件
注意,这里指的是“特定情况”,而不是按代码顺序执行时触发的,也就不是同步触发的,而是异步触发的。
所以,事件是异步触发的。
事物循环,顾名思义,就是事件的循环触发。没错,事件循环的核心就是“事件的循环触发”;
同时事件循环还包括,这些异步操作的触发,回调函数的收集以及回调函数的触发等一系列操作。这些操作其实贯穿整个JS代码的运行
综上所述:事件循环就是JS代码的运行机制。
另:
异步操作的触发, 其实是 同步执行的。
而回调函数的触发,是异步执行的
JS是单线程的,所以浏览器只会分配一个线程用来解析执行JS代码,同时所有的JS代码也只能在这一个线程中执行。此线程为JS引擎线程。
因为是单线程的,所以代码是同步执行的,也就是按代码顺序执行的,只有前一个任务执行完成,才能执行下一个任务。
那么如果实现在特定情况下触发函数呢?这就需要用于事件循环了
1)JS是解释型语言。所以JS是需要在宿主环境中才能运行的。而宿主环境是多线程的。
2)JS是单线程语言。所以宿主环境分配一个线程来解析运行JS代码。
3)宿主环境再利用其他线程来辅助完成其他的一些异步功能。同时创建相关任务队列,用来存储当异步功能完成后要调用的回调函数。
4)最后再循环将这些回调函数放入到JS引擎中的执行栈中,进行调用。
所以:JS的异步功能,是宿主环境的各线程相关联合实现的。而这整个过程可以称为事件循环
JS引擎运行JS代码涉及的几个概念
宿主环境实现事件循环涉及的几个概念
任务分类
JS中的任务指的是什么?
JS中的任务通常指的是需要通过代码完成的操作或功能。这些任务可以是简单的计划操作,也可以是复杂的功能;可以是一行代码,也可以是一个函。
异步任务中如何产生宏任务/微任务?
个人总结的执行顺序图解法:
图解法中的几条规则:
图解法评分分两个步骤:
2)根据任务节点图得出最终输出;
先上几个示例-用图解法
一、示例1
// 默认宏任务 :h0 ----- 同步任务
console.log("0");
setTimeout(function() { // 宏任务1 : h1
console.log("1");
new Promise(function(resolve, reject) {
console.log("2");
resolve();
}).then(() => {
console.log("3");
});
}, 0);
new Promise(function(resolve, reject) {
console.log("4"); // 同步任务
resolve();
}).then(() => {
console.log("5"); // 微任务
});
console.log("6"); // 同步任务
// 输出:0 4 6 5 1 2 3
图解

图解说明:
1)h0, h1 组成宏任务列表,若还有宏任务,则在下面添加节点
2)以 “t:” 为前缀的节点中,冒号后面的为同步任务输出。
3)以 “w:” 为前缀的节点中,冒号后面的为微任务输出。这里只有一个任务,所以就没有加序号了。
4)最后输出:先算出每个宏任务输出,然后再将每个宏任务输出按先后累加起来。
示例2
// h0 - 最外层同步任务
console.log(0)
// h1
setTimeout(() => {
// h3
setTimeout(()=>{console.log(6)},0)
console.log(1) //
var p2 = new Promise((n1, n2) => {
n1(1000)
})
p2.then(()=>{console.log(7)}) //
}, 0)
// h2
setTimeout(() => {
// h4
setTimeout(() => {console.log(2)}, 200) //
var p3 = new Promise((n1, n2) => {
n1(1000)
})
p3.then(()=>{console.log(8)})//
console.log(2)//
}, 0)
var p1 = new Promise((n1, n2) => {
n1(1000)
})
p1.then(() => {console.log(3)}) //
console.log(5) //
// 输出:4 5 3 1 7 2 8 6 2
图解-执行顺序

示例3
setTimeout(() => { // ----------- h1
console.log(0);
});
new Promise(resolve => {
console.log(1);
setTimeout(() => { // ----------- h2
resolve(); //这里!!!!!!!
var p1=new Promise((n1,n2)=>{n1(20)})
p1.then(() => console.log(2));
console.log(3);
setTimeout(()=>{console.log(9)},0) // ----------- h3
});
new Promise((n1,n2)=>{n1(20)}).then(() => console.log(4));
}).then(() => { //这里的then函数要等resolve()执行后才能执行 一点注意!!!
console.log(5);
var p2=new Promise((n1,n2)=>{n1(20)})
p2.then(() => console.log(8));
setTimeout(() => console.log(6)); // ----------- h4
});
console.log(7);
// 输出: 1 7 4 0 3 5 2 8 9 6

示例4
console.log(1)
setTimeout(() => {
setTimeout(()=>{console.log(2)},0)
console.log(3)
var p2 = new Promise((n1, n2) => {
n1(1000)
})
p2.then(()=>{console.log(4)})
}, 0)
setTimeout(() => {
setTimeout(() => {console.log(5)}, 200)
var p3 = new Promise((n1, n2) => {
n1(1000)
})
p3.then(()=>{console.log(6)})
console.log(7)
}, 0)
var p1 = new Promise((n1, n2) => {
n1(1000)
})
p1.then(() => {console.log(8)})
console.log(9)
// 输出 : 1 9 8 3 4 7 6 2 5

异步任务中如何产生宏任务/微任务?
执行顺序:
示例1(包括 setTimeout宏任务、nextTick微任务,普通微任务)
console.log('1');
async function async1() {
console.log('2');
await async2();
console.log('3');
}
async function async2() {
console.log('4');
}
process.nextTick(function() {
console.log('5');
})
setTimeout(function() {
console.log('6');
process.nextTick(function() {
console.log('7');
})
new Promise(function(resolve) {
console.log('8');
resolve();
}).then(function() {
console.log('9')
})
})
async1();
new Promise(function(resolve) {
console.log('10');
resolve();
}).then(function() {
console.log('11');
});
console.log('12');
// 输出 : 1 2 4 10 12 5 3 11 6 8 7 9

示例2
包括:setTimeout宏任务,setImmediate宏任务,process.nextTick微任务,promise.then微任务
console.log('1'); // 同1
setTimeout(function () { // 宏1
console.log('2'); // 宏1-同1
process.nextTick(function () { // 宏1-n微1
console.log('3');
})
new Promise(function (resolve) {
console.log('4'); // 宏1-同2
resolve();
}).then(function () {
console.log('5') // 宏1-微1
})
})
new Promise(function (resolve) {
console.log('6'); // 同2
resolve();
}).then(function () { // 微1
console.log('7')
})
process.nextTick(function () { // n微1
console.log('8'); //
})
setImmediate(() => { // 宏2
console.info('9') // 主线程和事件队伍的函数执行完成之后立即执行 和setTimeOut(fn,0)差不多
})
new Promise(function (resolve) {
console.log('10'); // 同3
resolve();
}).then(function () { // 微2
console.log('11')
})
setTimeout(function () { // 宏3
console.log('12');
setImmediate(() => {
console.info('13')
})
process.nextTick(function () {
console.log('14')
})
new Promise(function (resolve) {
console.log('15');
resolve();
}).then(function () {
console.log('16')
})
})
process.nextTick(function () { // n微2
console.log('17');
})
