JavaScript事件循环是一种机制,用于处理由于用户交互、异步操作或计时器等事件引起的回调函数。
JavaScript是一种单线程语言,意味着只能执行一个任务。事件循环通过维护一个事件队列来处理事件回调函数。当一个事件被触发时,相关的回调函数被推入事件队列中,并在适当的时候被执行。
事件循环由以下几个主要组件组成:
事件队列(Event Queue):用于存储待处理的事件回调函数。事件队列是一个先进先出(FIFO)的数据结构。
执行栈(Execution Stack):用于存储当前正在执行的代码。
主线程(Main Thread):负责执行JavaScript代码,并处理事件。
事件循环的工作流程如下:
JavaScript代码开始执行。
遇到异步任务(如定时器、AJAX请求等),将其添加到事件队列中。
执行栈为空时,事件循环从事件队列中取出第一个待处理的回调函数,并将其推入执行栈中。
执行栈开始执行回调函数的代码。
如果回调函数中包含了异步任务,将其添加到事件队列中。
执行栈为空时,重复步骤3-5。
通过事件循环,JavaScript能够以非阻塞方式处理异步任务,保证用户界面的响应性,并在需要时执行相应的回调函数。
console.log("Start");
setTimeout(function() {
console.log("Timeout 1");
}, 2000);
setTimeout(function() {
console.log("Timeout 2");
}, 1000);
console.log("End");
在这个例子中,我们使用setTimeout
函数来模拟异步任务。setTimeout
函数会在指定的时间延迟后将回调函数添加到事件队列中。在该代码中,我们使用两个setTimeout
函数,一个延迟时间为2秒,另一个延迟时间为1秒。
首先,我们会输出"Start",然后立即输出"End"。这是因为在执行这两行代码时,setTimeout
的回调函数还没有被执行,而是被添加到了事件队列中。
然后,事件循环会开始处理事件队列。在2秒后,事件队列中的第一个回调函数将被执行,输出"Timeout 1"。在另一个1秒后,事件队列中的第二个回调函数将被执行,输出"Timeout 2"。
因此,最终的输出顺序将是:
Start
End
Timeout 2
Timeout 1
这个例子展示了事件循环的基本工作原理,即在执行栈为空时,事件循环会从事件队列中取出待处理的回调函数并执行。
宏任务是由浏览器提供的任务源,包括但不限于以下几种:
而微任务是由JavaScript自身提供的任务源,包括但不限于以下几种:
在事件循环中,当执行栈为空时,事件循环会从宏任务队列中取出一个任务执行,当这个宏任务执行完毕后,会在执行下一个宏任务之前,检查并执行微任务队列中的任务。
举个例子,考虑以下代码:
console.log('Start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('Promise');
});
console.log('End');
执行顺序如下:
setTimeout
函数的回调函数添加到宏任务队列中。Promise
的.then
回调函数添加到微任务队列中。因此,最终的输出顺序为:
Start
End
Promise
setTimeout
宏任务会在事件循环的不同阶段执行,而微任务会在每个宏任务执行完毕后立即执行。这种执行顺序可以用来处理优先级较高的任务,并避免阻塞UI渲染。
async/await 是通过将异步操作包装在一个 Promise 中,然后使用 await 关键字来等待该 Promise 的解析结果。使用 async 关键字标记一个函数,这个函数将会返回一个 Promise 对象。
在一个使用 async 关键字标记的函数中,可以使用 await 关键字来等待一个返回 Promise 对象的表达式。await 关键字会暂停函数的执行,直到 Promise 对象被解析或拒绝。
以下是一个使用 async/await 的简单示例:
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function fetchData() {
console.log('Fetching data...');
await delay(2000); // 等待2秒钟
console.log('Data fetched!');
}
fetchData();
在上面的示例中,fetchData
函数是一个使用 async 关键字标记的异步函数。在函数内部,我们使用 await 关键字等待 delay
函数返回的 Promise 对象被解析,然后继续执行后续的代码。
在这个例子中,首先会打印 “Fetching data…”,然后等待2秒钟,最后打印 “Data fetched!”。
async/await 的优势在于它让异步代码的书写和理解更加直观和简单,避免了回调地狱和过多的嵌套。
需要注意的是,async/await 只能在支持 Promise 的环境中使用,如果要在老版本的浏览器中使用,可以通过使用 Babel 等工具进行转换。
JavaScript是一种广泛应用于网页开发的脚本语言,它可以用来为网页添加交互性和动态特效。JavaScript可以在网页中直接嵌入,也可以作为外部文件引用。
以下是JavaScript的一些重要特点和用法:
JavaScript是一种强大且灵活的语言,可以用来创建复杂的交互式网页,并且可以与HTML和CSS无缝配合,实现出色的用户体验。
【温故而知新】JavaScript的Document对象
【温故而知新】JavaScript的BOM之Screen/Location/History对象
【温故而知新】JavaScript的BOM之Navigator对象
【温故而知新】JavaScript的BOM之Window对象
【温故而知新】JavaScript数据结构详解
【温故而知新】JavaScript数据类型
RESTful API,如何构建 web 应用程序
jQuery实现轮播图代码
vue实现文本上下循环滚动
Vue运用之input本地上传文件,实现传参file:(binary)
js判断各种浏览器
uni-app详解、开发步骤、案例代码