首页 > 编程语言 >揭开 JavaScript 事件循环的神秘面纱

揭开 JavaScript 事件循环的神秘面纱

时间:2023-05-31 19:32:43浏览次数:56  
标签:异步 揭开 Web JavaScript 任务 API 面纱 setTimeout

Javascript 是一种单线程语言,这意味着它一次只能执行一个任务。但是,它仍然设法同时执行多项任务。它通过使用一些复杂的数据结构给人一种多线程的错觉。为实现这一点,Javascript 引擎有一个称为事件循环的重要组件。我们将了解什么是事件循环以及它如何在不阻塞主线程的情况下处理异步任务。

揭开 JavaScript 事件循环的神秘面纱_事件循环

什么是事件循环?

事件循环是 Javascript 中的一种机制,可以执行非阻塞异步操作。它允许 Javascript 在不阻塞主线程的情况下处理诸如从服务器获取数据、发出 HTTP 请求和处理用户事件等任务。

根据MDN Doc,它是一个运行时模型,它执行代码,收集和处理事件,并执行排队的子任务。了解事件循环的工作原理对于编写高效和高性能的代码至关重要。

为了更好地理解事件循环,让我们列出用于执行异步代码的组件 -

  1. 调用堆栈:JavaScript 使用调用堆栈来跟踪当前正在执行的函数(执行上下文)。当一个函数被调用时,它被添加到堆栈中,当它返回时,它被从堆栈中删除。
  2. Web API:Web API 由浏览器或 JavaScript 运行时环境提供,并提供 DOM 操作、计时器(setTimeout、setInterval)、XMLHttpRequest 等功能。这些 API 异步处理耗时的任务。JavaScript 与 Web API 交互,例如 DOM API、XMLHttpRequest 或 setTimeout,它们提供 JavaScript 引擎之外的功能。
  3. 任务队列:任务队列(也称为回调队列)保存准备好由事件循环处理的任务。当相关的异步操作完成时,这些任务就会入队。异步操作,例如计时器、用户事件和网络请求,由 Web API 处理。一旦这些操作完成,它们就会被放入任务队列中。
  4. 事件循环:事件循环不断检查两件事:调用堆栈和任务队列。如果 Call Stack 为空,则从 Task Queue 中取出第一个任务,并将其推送到 Call Stack 中执行。

通过代码示例了解事件循环

console.log('Start');

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

console.log('End');

复制

在这里,我们有 3 个控制台日志语句。但是其中一个控制台日志是在setTimeoutWeb API 中定义的。此 Web API 会将计时器设置为设置为setTimeout(此处我们已给出0ms)的值,一旦时间完成,setTimeoutWeb API 会将回调发送到任务队列。现在,它会一直留在那里直到邮件线程被释放,也就是说,执行堆栈变空。

这里需要注意的一点是,即使时间设置成0ms中的setTimeout,也会在最后执行。这是因为它setTimeout是一个带有定时器的异步任务,必须进入队列,然后等待主线程空闲。这个定时器可以是0 ms10000 ms无论如何,它仍然会被注册到任务队列中。下面的可视化图表清楚地解释了这一点——

动图

现在更清楚了,对吧?所以,这就是异步任务的工作方式。请注意,附加到 setTimeout 的时间是最小的,即代码至少不会在设置的时间内运行。但是只有在主线程释放后才会执行。假设您有一个 1000 毫秒的 setTimeout,但由于执行了一些复杂的操作,主线程花费了 2000 毫秒。在这种情况下,注册的 setTimeout 只能在 2000 毫秒后执行,而不是在 1000 毫秒后立即执行!

让我们深入研究下一个例子。我们将使用 XMLHttpRequest

console.log('Start');

var request = new XMLHttpRequest();
request.open('GET', 'https://api.example.com/data', true);
request.onreadystatechange = function() {
  if (request.readyState === 4 && request.status === 200) {
    console.log('Data received:', request.responseText);
  }
};
request.send();

console.log('End');

复制

我希望从前面的例子中你已经解码了上面的代码是如何工作的。是的,Http 异步请求将由 Web API 处理XMLHttpRequest。它将被处理并发送到任务队列中。Event Loop会一直等到主线程空闲,然后将任务Dqueue到Task Queue里面,放到Execution Stack中,由主线程执行。通过这个解释,我们可以说输出将是 -

Start
End
Data received: xyz // xyz is any response that API has sent

复制

结论

了解 JavaScript 事件循环对于编写高效且响应迅速的 JavaScript 代码至关重要。通过掌握其内部工作原理以及调用堆栈、Web API、任务队列和事件循环等组件的作用,您可以自信地处理异步任务并构建高性能的 Web 应用程序。有了这些知识,您就可以很好地处理复杂的场景并充分利用 JavaScript 的异步特性。

标签:异步,揭开,Web,JavaScript,任务,API,面纱,setTimeout
From: https://blog.51cto.com/u_15739596/6389129

相关文章

  • 关于第一次学习JavaScript程序调试心得
    源程序如上,源代码来源(刘永富博士-ExcelVBA编程开发下册)。运行之后,网页无反应,alert不弹窗。经查询https://www.runoob.com/jsref/event-body-onload.htmlhttps://blog.csdn.net/sinat_29398599/article/details/65450485需添加onload事件。Bodyonload事件,onload事件在页......
  • JavaScript中的Hook技术:特性、优点、缺点和使用场景
    引言:随着JavaScript的不断发展,开发者们正在寻找更灵活和可扩展的方式来修改或扩展现有的代码。其中一种广泛应用的技术是"Hook",它允许开发者拦截和修改现有的函数或方法的行为。本文将详细介绍JavaScript中的Hook技术,包括其特性、优点、缺点和使用场景,并提供示例代码进行说明。什么......
  • Javascript上传文件到阿里OSS存储,并支持进度查看
    现在使用js上传文件的插件有很多,例如:plupload等等今天我记录一下使用原生js的上传文件,并且支持进度查看,下面直接上代码:html代码:<inputtype="file"onchange="uploadMedia(this)"><aid="showProgress"style="display:none;"href="#"></a>预览效......
  • Python 执行Javascript脚本
    一、安装第三方库pipinstallPyExecJS二、创建一个js文件//test.jsfunctionadd(a,b){returna+b}三、创建一个python文件#testJs.pyimportexecjsctx=execjs.compile(open('./test.js','r',encoding='utf-8').read())print(ctx.call('add&#......
  • 智能社原生的力量——原生JavaScript开发高级
    智能社原生的力量——原生JavaScript开发高级download:3w51xuebccomSpringBoot3:打造高效的Java应用程序SpringBoot是一个由Pivotal团队开发的开源框架,它基于Spring框架,旨在使Spring应用程序的开发变得更加容易和快速。最新的SpringBoot版本是3.0.0,它带来了许多新特性和功能,让我......
  • let 和 const 是 JavaScript 中用于声明变量的关键字
    let和const是JavaScript中用于声明变量的关键字。let关键字用于声明可变(可重新赋值)的变量。通过使用let关键字声明的变量可以在其作用域内被重新赋值。例如:letx=10;x=20;//可以重新赋值const关键字用于声明不可变(不可重新赋值)的常量。通过使用con......
  • 逍遥自在学C语言 | 揭开while循环的神秘面纱
    前言循环是一种重要的控制结构,可以使程序重复执行一段代码,直到满足特定条件为止。在C语言中,while和do-while是两种常用的循环结构,本文将详细介绍这两种循环的用法。一、人物简介第一位闪亮登场,有请今后会一直教我们C语言的老师——自在。第二位上场的是和我们一起学习......
  • 什么是 JavaScript 里的循环引用(circular references)
    JavaScript的循环引用(circularreferences)是指在对象之间存在相互引用的情况,形成一个闭环,导致对象无法被完全释放和垃圾回收。循环引用发生在当一个对象的属性或成员引用另一个对象,并且这个被引用的对象又直接或间接地引用回原始对象,从而形成一个循环。当存在循环引用时,JavaScrip......
  • javascript常用正则表达式
    javascript身份证号验证正则1.//这个可以验证15位和18位的身份证,并且包含生日和校验位的验证。2.//如果有兴趣,还可以加上身份证所在地的验证,就是前6位有些数字合法有些数字不合法。3.4.function5.num=num.toUpperCase();6.//身份证号码为15位或者18......
  • Javascript编程风格
     所谓"编程风格"(programmingstyle),指的是编写代码的样式规则。不同的程序员,往往有不同的编程风格。 有人说,编译器的规范叫做"语法规则"(grammar),这是程序员必须遵守的;而编译器忽略的部分,就叫"编程风格"(programmingstyle),这是程序员可以自由选择的。这种说法不完全正确,程序员固然可......