一、介绍
1. 什么是js的事件循环
JavaScript事件循环是一种处理异步事件和回调函数的机制,它是JavaScript实现异步编程的核心。它在浏览器或Node.js环境中运行,用于管理任务队列和调用栈,以及在适当的时候执行回调函数。
2. 为什么会出现js的事件循环
JavaScript事件循环是为了解决JavaScript作为单线程语言时的并发性问题而设计的。由于JavaScript是单线程的,因此在执行代码时不能同时执行多个任务。这种单一线程的特性可能会导致JavaScript在处理某些长时间运行的操作(如网络请求、文件系统访问等)时出现阻塞,从而影响用户体验。
为了解决这些问题,JavaScript引入了异步编程模型和事件循环机制,它可以监听消息队列中的事件并根据优先级顺序依次执行相应的回调函数。这种机制允许JavaScript在等待某些操作完成的同时,可以执行其他任务,从而避免了阻塞,提高了效率和并发性,使得开发者可以使用异步编程模型来处理复杂的、长时间运行的操作,同时提供更好的用户体验。
3. 事件循环的流程
事件循环中的任务分为两类:同步任务和异步任务。同步任务是按照代码顺序依次执行的任务,而异步任务则是在任务队列中等待执行的任务,例如定时器回调函数、事件回调函数和Promise回调函数等。异步任务又可以分为宏任务和微任务,微任务的执行优先级高于宏任务。当一个宏任务中的所有微任务都执行完毕后,才会执行下一个宏任务。事件循环的工作流程是不断地从任务队列中取出任务并执行,直到队列为空为止。
二、事件循环的应用场景
- DOM 事件处理:通过监听 DOM 事件(例如 click、scroll 等),可以使用事件循环来异步更新 UI 或执行其他操作。
- 定时器:使用 setTimeout() 和 setInterval() 函数可以创建定时器,用于在指定时间间隔之后执行相应的操作。这些操作会被作为异步任务添加到任务队列中等待执行。
- 网络请求:当 JavaScript 需要发送网络请求时,可以使用 XMLHttpRequest 或 fetch API 发送异步请求,并将响应数据作为异步任务加入到任务队列中等待处理。
- Promise 和 async/await:Promise 和 async/await 是 JavaScript 中常用的异步编程方式,实际上它们底层都是基于事件循环机制实现的。通过将回调函数封装为 Promise 对象或 async 函数,可以让异步代码更加易读、易维护。
- Web Workers:Web Workers 可以让 JavaScript 在多线程环境下运行,从而避免阻塞主线程。Web Workers 使用了与事件循环类似的消息队列机制来实现异步通信。
三、例子
1. 定时器回调函数
console.log('start');
setTimeout(() => {
console.log('timer');
}, 0);
console.log('end');
// 输出结果
// start
// end
// timer
这是因为setTimeout()方法是异步执行的,它会在指定时间后将回调函数添加到任务队列中等待执行。因此,在输出"start"和"end"之后,程序立即返回,等到下一个事件循环时才执行定时器回调函数。
2. Promise回调函数
console.log('start');
Promise.resolve().then(() => {
console.log('promise');
});
console.log('end');
// 输出结果
// start
// end
// promise
这是因为Promise回调函数是微任务,它的执行优先级高于宏任务,因此在输出"start"和"end"之后,先执行Promise回调函数,再执行下一个宏任务。
3. 事件回调函数
console.log('start');
document.addEventListener('click', () => {
console.log('click');
});
console.log('end');
// 输出结果
// start
// end
这是因为事件回调函数需要等待用户操作才能触发,因此在程序执行完毕之后,等待用户操作后才会将回调函数添加到任务队列中等待执行。
四、复杂例子思考
async function a() {
console.log('async-a');
await b();
console.log('async-b');
};
async function b() {
console.log('async-b');
};
console.log('start');
setTimeout(()=>{
console.log('setTimeout-1');
},1000);
setTimeout(()=>{
console.log('setTimeout-2');
new Promise((resolve,reject)=>{
console.log('setTimeout-promise');
resolve('promise-1');
}).then(res => {
console.log(res);
})
},0);
new Promise((resolve,reject)=>{
console.log('promise');
resolve('promise-2');
}).then(res => {
console.log(res);
});
a();
console.log('end')
五、一句话总结
JavaScript事件循环是一种处理异步事件和回调函数的机制,它是JavaScript实现异步编程的核心。它会不断地从任务队列中取出任务并执行,直到任务队列为空为止。事件循环中的任务分为同步任务和异步任务,异步任务又可以分为宏任务和微任务,微任务的执行优先级高于宏任务。