【温故而知新】JavaScript事件循环

2024-01-08 10:32:42

一、概念

JavaScript事件循环是一种机制,用于处理由于用户交互、异步操作或计时器等事件引起的回调函数。

JavaScript是一种单线程语言,意味着只能执行一个任务。事件循环通过维护一个事件队列来处理事件回调函数。当一个事件被触发时,相关的回调函数被推入事件队列中,并在适当的时候被执行。

事件循环由以下几个主要组件组成:

  1. 事件队列(Event Queue):用于存储待处理的事件回调函数。事件队列是一个先进先出(FIFO)的数据结构。

  2. 执行栈(Execution Stack):用于存储当前正在执行的代码。

  3. 主线程(Main Thread):负责执行JavaScript代码,并处理事件。

事件循环的工作流程如下:

  1. JavaScript代码开始执行。

  2. 遇到异步任务(如定时器、AJAX请求等),将其添加到事件队列中。

  3. 执行栈为空时,事件循环从事件队列中取出第一个待处理的回调函数,并将其推入执行栈中。

  4. 执行栈开始执行回调函数的代码。

  5. 如果回调函数中包含了异步任务,将其添加到事件队列中。

  6. 执行栈为空时,重复步骤3-5。

通过事件循环,JavaScript能够以非阻塞方式处理异步任务,保证用户界面的响应性,并在需要时执行相应的回调函数。

二、案例

  1. 一个简单的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

这个例子展示了事件循环的基本工作原理,即在执行栈为空时,事件循环会从事件队列中取出待处理的回调函数并执行。

  1. 宏任务(macrotask)和微任务(microtask)
    在JavaScript中,事件循环中的任务分为两类:宏任务(macrotask)和微任务(microtask)。它们的执行顺序有所不同。

宏任务是由浏览器提供的任务源,包括但不限于以下几种:

  • setTimeout
  • setInterval
  • I/O 操作
  • 页面渲染

而微任务是由JavaScript自身提供的任务源,包括但不限于以下几种:

  • Promise
  • MutationObserver
  • process.nextTick(在Node.js中)

在事件循环中,当执行栈为空时,事件循环会从宏任务队列中取出一个任务执行,当这个宏任务执行完毕后,会在执行下一个宏任务之前,检查并执行微任务队列中的任务。

举个例子,考虑以下代码:

console.log('Start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('Promise');
});

console.log('End');

执行顺序如下:

  1. 输出"Start"。
  2. setTimeout函数的回调函数添加到宏任务队列中。
  3. Promise.then回调函数添加到微任务队列中。
  4. 输出"End"。
  5. 此时,执行栈为空,事件循环会检查微任务队列,执行微任务中的函数,输出"Promise"。
  6. 最后,事件循环会执行宏任务队列中的任务,输出"setTimeout"。

因此,最终的输出顺序为:

Start
End
Promise
setTimeout

宏任务会在事件循环的不同阶段执行,而微任务会在每个宏任务执行完毕后立即执行。这种执行顺序可以用来处理优先级较高的任务,并避免阻塞UI渲染。

  1. async/await
    async/await 是 ECMAScript 2017 中引入的一种异步编程的语法糖,它基于 Promise 实现,使得异步代码的编写更加简洁和易读。

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的一些重要特点和用法:

  1. 脚本语言:JavaScript是一种解释型脚本语言,不需要编译,可以直接在浏览器中执行。
  2. 弱类型语言:JavaScript是一种弱类型语言,变量的数据类型可以随时改变,不需要声明变量的类型。
  3. 事件驱动:JavaScript可以通过监听用户的操作或者其他事件触发特定的代码执行,实现网页的交互性。
  4. DOM操作:JavaScript可以通过文档对象模型(DOM)来操作网页的HTML元素,可以动态地添加、修改和删除元素。
  5. 表单验证:JavaScript可以通过表单验证来确保用户输入的数据符合要求,提供更好的用户体验。
  6. AJAX:JavaScript可以通过AJAX技术实现网页的异步加载,可以在不刷新整个页面的情况下更新部分内容。
  7. JSON:JavaScript Object Notation(JSON)是一种轻量级的数据交换格式,JavaScript可以很方便地解析和生成JSON数据。
  8. 库和框架:JavaScript拥有丰富的库和框架,如jQuery、React、Angular等,可以简化开发过程并提供更强大的功能。

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详解、开发步骤、案例代码

文章来源:https://blog.csdn.net/xuaner8786/article/details/135449866
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。