超高频面试题之JS单线程与事件循环,看这篇就够了

【前端面试题】事件循环event_loop JavaScript是一个单线程语言。 任务分为同步任务和异步任务。 同步任务就是立即执行的任务,同步任务会进入主线程立即执行,当浏览器遇到异步任务时,会将异步任务扔到异步队列中去,等同步任务执行完毕后,再按照“微先宏后”的执行顺序依次执行异步任务。 “微先宏后”就是在异步任务队列中微任务先执行,宏任务后执行。 微任务包括:promise 宏任务包括:setTimeout、setInterval、UI交互、IO、script整体代码 下面来看面试题,先看题目,思考后有自己的想法再看题目结果,有不 阅读详情

JavaScript是一种单线程语言,它在任何给定时间只能执行一个任务。然而js确能够处理异步操作,这得益于其事件循环(Event Loop)机制。今天这篇文章带领大家深入理解JavaScript单线程特性,以及讲解事件循环和js多线程知识。

一、背景:为什么JS是单线程?

在最开始设计中,JS的主要用途是处理浏览器中的用户界面事件。由于JS交互直接进行DOM操作,如果允许多线程对DOM进行并行操作,可能会导致竞态条件,例如一个线程正在读取节点,而另一个线程正在修改它。这将导致程序的不可预测性,因此,JS被设计为单线程语言,以避免这种复杂性。

二、事件循环

事件循环的核心思想是:JS引擎首先执行当前的同步任务,然后检查任务队列(Task Queue)中是否有待处理的异步任务。如果有,它会按照顺序将这些异步任务添加到执行队列,并在当前任务执行完毕后依次执行它们。在这个过程中,宏任务和微任务是两种不同类型的异步任务,它们在事件循环中的处理方式有所不同。

2.1 宏任务(MacroTask)

宏任务是指那些需要在下一个事件循环周期执行的任务。常见的宏任务包括:

  • setTimeout
  • setInterval
  • setImmediate(Node.js 独有)
  • I/O 操作(Node.js 独有)
  • UI 渲染(浏览器独有)

当事件循环执行到一个宏任务时,它会将该任务添加到宏任务队列中。在当前事件循环周期结束时,JS引擎会检查宏任务队列,并将队列中的任务依次执行。

2.2 微任务(MicroTask)

微任务是指那些在当前事件循环周期内执行的任务。常见的微任务包括:

  • Promise.then 和 Promise.catch
  • async/await(实际上是基于 Promise 的语法糖)
  • process.nextTick(Node.js 独有)
  • MutationObserver(浏览器独有)

当事件循环执行到一个微任务时,它会将该任务添加到微任务队列中。与宏任务不同,微任务会在当前事件循环周期内立即执行,而不是等待下一个事件循环周期。

2.3 事件循环处理宏任务和微任务的顺序

  1. 从宏任务队列中取出一个任务并执行。
  2. 检查微任务队列,如果有任务,则依次执行所有微任务。
  3. 检查宏任务队列,如果有任务,则返回步骤1,否则等待新任务。

这意味着,在一个事件循环周期中,微任务会在宏任务之间执行。换句话说,当一个宏任务执行完毕后,JS引擎会检查微任务队列,并在执行下一个宏任务之前执行所有的微任务。

下面是一个简单的示例,展示了宏任务和微任务在事件循环中的执行顺序:

console.log('Start'); // 同步任务

setTimeout(() => {
    console.log('setTimeout'); // 宏任务
}, 0);

Promise.resolve().then(() => {
    console.log('Promise'); // 微任务
});

console.log('End'); // 同步任务

输出顺序为:

Start
End
Promise
setTimeout

这是因为在执行到 setTimeout 时,它被添加到宏任务队列中。而在执行到 Promise 时,它被添加到微任务队列中。在当前事件循环周期结束之前,JS引擎会先执行微任务队列中的所有任务,然后再执行宏任务队列中的任务。

事件循环是JavaScript运行时环境的核心组件,负责处理宏任务和微任务。了解宏任务和微任务在事件循环中的执行顺序,有助于我们更好地理解和编写异步代码。

三、 异步编程

  1. 回调函数:最基本的异步编程模型,将一个函数作为参数传递给另一个函数,当异步操作完成时,回调函数被执行。
function downloadFile(url, callback) {
    // 模拟异步操作
    setTimeout(() => {
        console.log(`Downloaded file from ${url}`);
        callback();
    }, 2000);
}

downloadFile('https://example.com/file.txt', function() {
    console.log('File download complete');
});
  1. Promise:Promise是一种更高级的异步编程模型,它表示一个异步操作的最终结果。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
function downloadFile(url) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(`Downloaded file from ${url}`);
            resolve();
        }, 2000);
    });
}

downloadFile('https://example.com/file.txt')
    .then(() => {
        console.log('File download complete');
    });
  1. async/await:async/await是基于Promise的一种更简洁的异步编程模型。通过使用async关键字声明一个函数为异步函数,然后在函数内部使用await关键字等待Promise的结果。
async function downloadFile(url) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(`Downloaded file from ${url}`);
            resolve();
        }, 2000);
    });
}

(async () => {
    await downloadFile('https://example.com/file.txt');
    console.log('File download complete');
})();

三、单线程的优缺点

3.1 优点

  1. 避免了多线程下的复杂性,如死锁。
  2. 简化了异步操作,使得异步编程更易于构建和理解。

3.2 缺点

  1. 长时间运行的任务可能会阻塞线程,影响用户体验。
  2. 无法充分利用多核CPU的计算能力。

四、实现多线程的方法

尽管JS是单线程,但我们可以通过Web Workers在浏览器中创建多个线程。Web Workers运行在后台线程中,不影响主线程,它们之间通过postMessage来进行通信。

4.1 Web Workers

这是一个简单的Web Worker示例,演示了多个进程之间的通信:

// main.js
const worker = new Worker('worker.js');

worker.postMessage('Hello, Worker!');

worker.onmessage = function(event) {
    console.log('Message from worker:', event.data);
};

// worker.js
self.onmessage = function(event) {
    console.log('Message from main thread:', event.data);
    self.postMessage('Hello, Main Thread!');
};

4.2 SharedArrayBuffer与Atomics

为了实现更高级的多线程编程,JS引入了SharedArrayBuffer和Atomics对象。SharedArrayBuffer允许多个Web Workers共享同一块内存,而Atomics对象提供了一组原子操作,确保在多线程环境下对共享内存的操作是安全的。

以下是一个使用SharedArrayBuffer和Atomics的示例:

// main.js
const worker = new Worker('worker.js');
const sharedBuffer = new SharedArrayBuffer(4);
const sharedArray = new Int32Array(sharedBuffer);

worker.postMessage(sharedBuffer);

Atomics.store(sharedArray, 0, 1);
console.log('Main thread set value:', sharedArray[0]);

worker.onmessage = function(event) {
    console.log('Message from worker:', event.data);
};

// worker.js
self.onmessage = function(event) {
    const sharedBuffer = event.data;
    const sharedArray = new Int32Array(sharedBuffer);

    console.log('Worker thread initial value:', sharedArray[0]);
    Atomics.add(sharedArray, 0, 1);
    console.log('Worker thread updated value:', sharedArray[0]);

    self.postMessage('SharedArrayBuffer updated');
};

4.3 使用Web Workers的注意事项

  1. Web Workers无法访问主线程的全局变量和函数。
  2. Web Workers无法直接操作DOM。
  3. 通信开销:Web Workers之间的通信需要通过postMessage和onmessage事件进行,这会带来一定的性能开销。

总结

JS的单线程特性使得编程模型简单易懂,但也带来了一些限制。通过使用事件循环、异步编程模型和Web Workers,我们可以在很大程度上克服这些限制,进而实现高性能的Web应用。

[CTFSHOW]JWT 文章目录前言JWT简介CTFSHOW Web345CTFSHOW Web346前置知识开始做题CTFSHOW Web347CTFSHOW Web348CTFSHOW Web349CTFSHOW Web350前置知识利用WP如何防御 前言 有些师傅向我咨询WP,索性就发了吧,其实早就写好了,只是懒,在github仓库里囤着 JWT简介 可以看看我的Github总结给自己看的,Y4tacker CTFSHOW Web345 首先打开题目,查看源码,接下来访问/admin被跳转回主页啥也没有发生 where is 阅读详情

相关推荐

用Python+OpenCV搞定线激光相机标定:从棋盘格到3D点云的保姆级实战

本文详细介绍了使用Python和OpenCV进行线激光相机标定的全流程实战,从硬件准备到3D点云重建。涵盖相机内参标定、激光平面方程拟合、三维重建等关键技术,提供完整的代码实现和工程优化建议,帮助开发者实现毫米级精度的工业检测和三维测量系统。

weixin_29227425的博客 287

面试题:事件循环(Event Loop)

在日常工作中,你有没有碰到过这种疑惑: 疑惑一:为什么这份代码它不按照我的意思走?为啥不是输出 1 2 3? for (var i = 0; i < 3; i++) { setTimeout(() => { console.log(i); // 3 3 3 }, 1000); } 疑惑二:为什么这份代码它也不按照我的意思走?为啥不是输出 jsliang? let name; setTimeout(() => { name = '梁峻荣'; console

明天也要努力的博客 5693

E-Prime脑电实验打mark全攻略:从端口查询到串并口实战(附常见问题解决)

本文提供了E-Prime脑电实验打mark的完整实战指南,涵盖端口查询、并口与串口配置的核心步骤及常见问题解决。文章深入解析了mark原理,并详细介绍了通过E-Basic脚本和Serial设备对象发送信号的两种方法,帮助研究者实现E-Prime与脑电设备的高精度时间同步,确保实验数据可靠性。

4k5l6j7h8的博客 355

JS事件循环和经典异步面试题

关于JS 这个标题下,我们只需要牢记一句话:JavaScript 是单线程语言 既然JavaScript是单线程语言,那么就会存在一个问题,所有的代码都得一句一句的来执行。就像我们在食堂排队打饭,必须一个一个排队点菜结账。那些没有排到的,就得等着~ 事件循环(Event Loop) JavaScript有一个主线程main thread,和调用栈call-stack也称之为执行栈。所有的任务都会放到调用栈中等待主线程来执行。 JavaScript的Event Loop是伴...

微光的博客 2530

C++ muduo网络库知识分享01 - Linux平台下muduo网络库源码编译安装

Muduo is a multithreaded C++ network library based on the reactor pattern. muduo库的介绍就是:一个基于reactor反应堆模型的多线程C++网络库。 muduo网络库是C++语言开发的一个非常优秀的网络库,作者陈硕,muduo网络库在多线程环境下性能非常高,该系列文章会分享一些muduo库源码的知识,包括它的线程池源码...

大秦坑王的专栏 3万+

来!简单了解一下计算机发展史!

​ 1936年,英国数学家阿兰・麦席森・图灵提出了一种抽象的计算模型——图灵机( Turing machine)。图灵机,又称图灵计算机,即将人们使用纸笔进行数学运算的过程进行抽象,由一个虚拟的机器替代人类进行数学运算。​ 图灵机是一个抽象的机器,它有一条无限长的纸带,纸带分成了一个一个的小方格,每个方格有不同的颜色。有一个机器头在纸带上移来移去。机器头有一组内部状态,还有一些固定的程序。

m0_57290404的博客 2907

面试题 - 事件循环机制

一、浏览器JS异步执行的原理 一般常说js是一门单线程语言,那为什么可以异步执行且不发生阻塞呢? 常说的JS是单线程语言,是因为执行JS的引擎是单线程的,而浏览器本身是多线程的 浏览器主要含有: js 执行线程 定时器线程 http 请求线程 事件触发线程 GUI 线程等 异步请求的真正执行者是浏览器的其他线程 js 引擎只是执行了异步操作成功了之后的回调函数 二、事件循环机制 1 - 执行栈和任务队列 (1)执行栈是什么 用于按执行顺序存放同步代码 按序执行,执行完毕后弹出执行栈 如果在执

bug处理进行时 5067

量化策略分享 | MA超进化:LLT低延迟趋势线

移动平均线(MA)是我们技术分析中常用的一种趋势跟踪指标,但在使用的时候你是否也会有这样的烦恼:交易信号延迟太久,或者交易信号太频繁了!延迟性和平滑性问题似乎是不可兼得的“鱼和熊掌”。 针对这个问题,广发证券基于通信领域的滤波器原理,在《短线择时策略研究之三:低延迟趋势线与交易性择时》中创造性构建了:LLT低延迟趋势线(Low-lag Trendline)。 LLT低延迟趋势线是一种二阶滤波器,阶数相对适宜,相比MA、EMA等均线指标能够降低延迟,同时增强在低频部分的输出信号。 当然,..

量化交易研究 5309

js事件循环

javascript 是单线程脚本语言,那么为什么不像 java 一样变成多线程,它不香吗?让我们来看一个问题,如果 js 是多线程,那么来看看执行下面这段代码-- 浏览器解析 h1标签的时候,渲染为红色 --> < script > document . querySelector("h1") . style . css . color = "green";// 上面这条js代码也找到h1标签,渲染为绿色 stylecolorred;

yy869949908的博客 1167

【上海大学计算机组成原理实验报告】五、机器语言程序实验

机器语言程序实验//理解计算机执行程序的实际过程//学习编制机器语言简单程序的方法//将R1中的数值左移n次送OUT,其中n是R2中的数值。(指令码从10开始)//完成R3=R0×R1,结果送OUT。(指令码从30开始)//建立“中文汇编指令”需要哪些条件?//上海大学计算机组成原理实验报告

HackerKevon的博客 2188

Android Input——输入系统介绍(一)

Input 系统对于提供流畅、灵敏和一致的用户交互体验至关重要,它需要在不同的设备、场景和应用中保证输入事件的正确性、及时性和安全性。Android 输入系统是一个复杂但高效的设计,旨在处理来自各种输入设备(如触摸屏、键盘等)的用户交互,并将这些交互转换为应用程序可以理解和响应的形式。EventHub:输入系统的最底层,直接与硬件通信,监听和读取输入设备的原始事件。:从 EventHub 获取原始输入事件,对其进行解析,转化为更高层次的事件,以便上层应用或服务能够理解。

小旭的专栏 1712

【web前端之超高频面试题整理】JS篇

JavaScript作为Web前端开发的核心语言,其面试题目覆盖了从基础语法到复杂的异步编程、内存管理等多个层面。本文精心整理了JavaScript高频面试题,涵盖闭包、事件循环、Promise、模块化、原型链、this 关键字等关键知识点。通过对每个问题的详细讲解与代码示例,本篇文章将为你提供一套全面的备考指南,助力你在面试中脱颖而出。

longshehui的博客 1388

xilinx原语及bank简介

图8是HP bank与HR bank的IO模块,其中PAD是FPGA的金属管脚,IOB是输入、输出引脚的控制模块。此时使用原语就可以只调用需要的组件,不需要去考虑其余组件参数设置,就方便很多,借助此次机会就对IDDR、ODDR、IDELAYE2、ODELAYE2、IDELAYCRTL、ISERDESE、OSERDESE等几个原语做了简要了解,并对原语的各个模式进行了仿真,本文最初是介绍IDDR的,但在介绍IDDR这些原语之前,还需要了解一下7系列FPGA bank的分类和区别,所以就有了本文。

qq_43416206的博客 413

前端面试题二

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、HTML/CSS1、HTML语义化2、CSS选择器3、@import与link4 盒模型5、清除浮动清除浮动的方式使用 clear 属性清除浮动的原理?zoom:1 的清除浮动原理?6、水平居中/垂直居中7、相对/绝对定位8、Flex布局9、伪类、伪元素10、行内/块级11、隐藏元素方式12、CSS3新增纯 CSS 创建一个三角形的原理13、CSS动画14、.CSS 中哪些属性可以继承?15、Display16、Positi

weixin_44770030的博客 2951

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

【笔记整理】前端面经

收集所有面试要点,大部分是实际面试问题,个别是提升时需要掌握的知识点

m0_53852077的博客 1445

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

JS事件循环机制 面试题

执行结果1.2.案例执行结果1.3.案例执行结果1.4 先执行 宏任务当中的同步任务 --> 微任务当中的同步任务 --> 微任务当中的异步任务 --> 宏任务中的异步任务。

weixin_65251013的博客 1221

事件循环(2024 面试题)

定时器检测阶段(timers):本阶段执行 timer 的回调,即 setTimeout、setInterval 里面的回调函数。I/O事件回调阶段(I/O callbacks):执行延迟到下一个循环迭代的 I/O 回调,即上一轮循环中未被执行的一些I/O回调。闲置阶段(idle, prepare):仅系统内部使用。轮询阶段(poll):检索新的 I/O 事件;

qq_16546829的博客 2688

通俗易懂,最完整 ------- 事件循环详解以及必备面试问答题(附答案)

程序运行需要有它自己专属的内存空间,可以把这块内存空间简单理解为进程每个应用至少有一个进程,进程之间相互独立,即使要通信,也需要双方同意。

柑橘乌云_ 2411

js事件循环机制及面试题详解

学习js必不可少的知识点插入

JessicaLi的博客 5405

事件循环(Event Loop)相关概念 及 面试题

小伙伴们,看面试题前,先来看几个概念吧!!! 宏任务 (macro)task,可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。 任务(代码) 宏任务 环境 script 宏任务 浏览器 事件 宏任务 浏览器 网络请求(Ajax) 宏任务 浏览器 setTimeout() 定时器 宏任务 浏览器 / Node fs.readFile() 读取文件 宏任务 N

m0_67841039的博客 1186

【JavaScript】事件循环、宏/微任务、面试题

🔴:计算机,是的一种方式;🔴:操作系统能够运行,通常情况下中;听起来很抽象,这里还是给出我的解释:✅:我们可以认为,启动,就会默认(也可能是多个进程);✅:每中,都会启动用来执行程序中的代码,这个线程被称之为;✅ 所以我们也可以说进程是线程的容器;

羊羊羊羊羊羊羊的博客 1632

js事件循环机制面试题

js事件循环机制

qq_46067877的博客 499

面试必会js事件循环机制( JavaScript事件循环机制详解与面试输出题分析)

JavaScript事件循环机制是理解异步编程的关键。JavaScript是单线程语言,通过事件循环协调异步任务的执行。任务分为同步任务和异步任务,异步任务又细分为宏任务(如setTimeout)和微任务(如Promise.then)。事件循环的执行流程是:先执行同步任务,然后每轮循环清空微任务队列,再执行一个宏任务,直至所有队列清空。在做输出题时,建议用纸笔列出输出栈、宏任务和微任务,模拟出入队列以避免心算出错。通过分析示例代码,可以更好地掌握事件循环的执行顺序和任务调度。

weixin_72680176的博客 1087

前端面试题---事件循环机制和异步编程

前端面试题,事件循环(Event Loop)机制,异步操作的方式,回调函数,Promises,异步/等待(Async/Await)

前端卷王小白的博客 1138

彻底理解js是单线程的

JS执行是单线程 单线程是指Js引擎执行Js时只分了一个线程给他执行,也就是执行js时是单线程的。 那么问题来了,什么是线程?进程又是什么? 在分析浏览器的渲染过程之前,我们先了解一下什么是进程和线程: (1)什么是进程? 进程是CPU进行资源分配的基本单位 (2)什么是线程? 线程是CPU调度的最小单位,是建立在进程的基础上运行的单位,共享进程的内存空间。 多进程 1、浏览器是多进程 2、不...

前端精髓 1万+

【JS基础】克服事件循环机制的基础面试题,一点也不难

本次文章默认阅读者已掌握JS的单线程和异步的特性,以及事件循环机制的基本原理。内容如有错误欢迎指出。

庞囧的博客 1790

分享关于事件循环的几道面试题。

放入微任务队列,主线程任务做完,在调用微任务队列里的微任务,输出“3”6.微任务做完,开始做第二个宏任务,由于resolve(6),将与其对应的then的回调函数放入微任务队列中。7.与步骤五一样,开始做微任务队列,输出传进去的data,输出“6”再将输出“8”的计时器放入宏任务队列中,在输出“9”5.第一个宏任务做完,开始做微任务,故来到then的回调函数中,输出“3”,并将输出“5”的定时器放入宏队列中。2、在one函数中,立即执行await右边的函数,输出“4”,再将后面的任务都放入微任务队列里。

2401_87313302的博客 625
上一篇: 揭秘前端滑块验证技术
下一篇: 前端实现水印效果的多种方案
前端大师兄
博客等级 码龄16年 32粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值