js事件循环机制

83 阅读2分钟

js的事件循环机制是为了实现异步

JavaScript是单线程语言,单线程就是说在同一时刻只能执行一个任务。而事件循环机制可以让JavaScript实现异步操作,不用等上一个异步函数完全执行完再执行下一个。

事件循环机制的具体执行

  1. 代码执行时,先执行同步任务,然后将异步任务放入相应的任务队列中等待执行。任务队列中的任务分为宏任务和微任务,分别存在宏任务队列和微任务队列。
  2. 当所有同步任务执行完毕,js会清空微任务队列中的微任务。
  3. 清空微任务队列后,js会去宏任务队列取出一个宏任务执行。
  4. 循环执行微任务和宏任务,直到两个队列都清空。

宏任务:setTimeout,setInterval,I/O操作 微任务:Promise,MutationObserver,process.nextTick

宏任务和微任务的区别

宏任务通常由浏览器或者node环境发起,适用于周期性任务。

微任务优先级高于宏任务,适用于需要尽快执行的任务。比如与数据处理相关的任务,可以放入微任务队列中,在下一轮页面渲染之前完成。

事件循环实例


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");
});
async1();
new Promise(function (resolve) {
	console.log("promise1");
	resolve();
}).then(function () {
	console.log("promise2");
});
console.log("script end");

结果:

// script start
//               settimeout 宏
// async1 start
// async2
//                               async1 end 微
// promise1                      promise2 微
// script end
//
// async1 end
// promise2
// settimeout

console.log("1");


setTimeout(function () {
	console.log("2");
	process.nextTick(function () {
		console.log("3");
	});
	new Promise(function (resolve) {
		console.log("4");
		resolve();
	}).then(function () {
		console.log("5");
	});
});
process.nextTick(function () {
	console.log("6");
});
new Promise(function (resolve) {
	console.log("7");
	resolve();
}).then(function () {
	console.log("8");
});


setTimeout(function () {
	console.log("9");
	process.nextTick(function () {
		console.log("10");
	});
	new Promise(function (resolve) {
		console.log("11");
		resolve();
	}).then(function () {
		console.log("12");
	});
});

结果:

// 首先将两个settimeout中的函数视为一个整体
// 1
//     settimeout_1宏
//                    6微
// 7                  8微
//     settimeout_2宏

// 展开两个定时函数中的代码
// 1
//     settimeout_1宏
//                    6微√
// 7                  8微√
//     settimeout_2宏
// 6(微)
// 8(微)
// 2(settimeout_1宏)
// 4(settimeout_1宏)
// 3(settimeout_1宏)
// 5(settimeout_1宏)
// 9(settimeout_2宏)
// 11(settimeout_2宏)
// 10(settimeout_2宏)
// 12(settimeout_2宏)

const promise = new Promise((resolve, reject) => {
	resolve("10");
})
	.then(res => {
		console.log("res1:", res); //res1
		return 9;
	})
	.then(res => {
		console.log("res2:", res); //res2: 9
		return 8;
	})
	.then(res => {
		console.log("res3:", res); //res3: 8
		let promise2 = new Promise((resolve, reject) => {
			resolve("p2");
		}).then(res => {
			console.log(res); //p2
			setTimeout(function () {
				console.log("setTimeout2");
			}, 0);
		});
	});
console.log("aaa");
setTimeout(function () {
	console.log("setTimeout1");
}, 0);

const promise1 = new Promise((resolve, reject) => {
	console.log("p1");
	resolve(989);
})
	.then(res => {
		console.log(res); //989
		return 990;
	})
	.then(res => {
		console.log(res); //990
		return 991;
	})
	.then(res => {
		console.log(res); //991
		return 0;
	});

结果

image.png

setTimeout(function () {
	console.log("set1");
	new Promise(function (resolve) {
		resolve();
	}).then(function () {
		new Promise(function (resolve) {
			resolve();
		}).then(function () {
			console.log("then4");
		});
		console.log("then2");
	});
});

new Promise(function (resolve) {
	console.log("pr1");
	resolve();
}).then(function () {
	console.log("then1");
});

setTimeout(function () {
	console.log("set2");
});

console.log(2);

queueMicrotask(() => {
	console.log("queueMicrotask1");
});

new Promise(function (resolve) {
	resolve();
}).then(function () {
	console.log("then3");
});

结果

image.png