浏览器与 Node 的事件循环

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
性能测试 PTS,5000VUM额度
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 浏览器和Node.js的事件循环是异步操作的核心机制。它们通过管理任务队列和回调函数,确保程序在处理耗时任务时不会阻塞主线程,从而实现高效、响应式的应用开发。
  1. 浏览器中的事件循环
    • 执行栈(Call Stack)
      • 执行栈是一个后进先出(LIFO)的数据结构,用于存储在代码执行期间创建的函数调用。当一个函数被调用时,它就会被添加到执行栈的顶部,当这个函数执行完成后,它就会从执行栈的顶部被移除。例如,在下面的JavaScript代码中:
        function foo() {
                 
        console.log('foo');
        }
        function bar() {
                 
        foo();
        }
        bar();
        
      • 首先bar函数被调用并压入执行栈,在bar函数内部调用foo函数,foo函数又被压入执行栈,当foo函数执行完毕(打印foo后),它从执行栈弹出,然后bar函数执行完毕也从执行栈弹出。
    • 任务队列(Task Queue)
      • 任务队列分为宏任务队列(Macro - task Queue)和微任务队列(Micro - task Queue)。宏任务包括script(整体代码)、setTimeoutsetIntervalI/O操作、postMessageMessageChannel等。微任务包括Promise.thenMutationObserver等。
      • 当执行栈为空时,事件循环会检查微任务队列。如果微任务队列中有任务,就会将微任务队列中的任务依次取出并压入执行栈执行,直到微任务队列为空。例如:
        console.log('start');
        Promise.resolve().then(() => {
                 
        console.log('micro - task');
        });
        setTimeout(() => {
                 
        console.log('macro - task');
        }, 0);
        console.log('end');
        
      • 输出顺序是startendmicro - taskmacro - task。因为Promise.then中的任务是微任务,会在执行栈为空后且在检查宏任务队列之前执行,而setTimeout中的任务是宏任务,会在微任务队列清空后且执行栈再次为空时执行。
    • 渲染(Render)
      • 浏览器通常会在一个宏任务执行完毕后,且在执行下一个宏任务之前进行渲染。不过,这也不是绝对的,浏览器会根据自身的优化策略和任务的紧急程度等来决定是否进行渲染。例如,在一个复杂的动画场景中,浏览器可能会更频繁地进行渲染以保证动画的流畅性。
  2. Node.js中的事件循环
    • 阶段(Phases)
      • Node.js的事件循环分为6个阶段,分别是timerspending callbacksidle, preparepollcheckclose callbacks
      • timers阶段:这个阶段会执行setTimeoutsetInterval的回调函数。需要注意的是,这些回调函数的执行时机并不是严格按照设置的时间来的,而是在进入timers阶段且满足时间条件时才会执行。例如,如果在setTimeout回调函数之前有一个长时间运行的同步操作,那么setTimeout回调函数可能会延迟执行。
      • pending callbacks阶段:处理一些系统操作(如TCP错误回调等)的回调函数,这些回调函数在之前的轮询中可能没有被处理完。
      • idle, prepare阶段:这是内部使用的阶段,主要用于一些准备工作。
      • poll阶段:这是一个比较复杂的阶段。它主要有两个功能。一是等待新的I/O事件;二是在适当的时候执行与I/O相关的回调函数。如果没有新的I/O事件,它会检查timers阶段是否有到期的定时器,如果有就会回到timers阶段执行定时器的回调函数。
      • check阶段:主要用于执行setImmediate的回调函数。setImmediate是Node.js特有的一个函数,它的回调函数会在check阶段执行。
      • close callbacks阶段:用于执行close事件的回调函数,比如socket.on('close', callback)中的callback函数。
    • Node.js与浏览器事件循环的区别
      • 任务类型的差异:Node.js有自己独特的任务阶段划分,如setImmediateprocess.nextTickprocess.nextTick是一个特殊的微任务,它会在当前操作完成后立即执行,甚至优先于其他微任务。而浏览器没有setImmediateprocess.nextTick这些概念。
      • I/O处理的重点不同:Node.js更侧重于服务器端的I/O处理,事件循环的设计也更注重高效处理大量的I/O请求。例如,在Node.js的poll阶段,对I/O事件的等待和处理是核心功能之一。而浏览器的事件循环主要是为了处理用户交互、页面渲染以及网络请求等浏览器相关的任务。
相关文章
|
6月前
|
JavaScript 前端开发 算法
Node.js中的process.nextTick与浏览器环境中的nextTick有何不同?
Node.js中的process.nextTick与浏览器环境中的nextTick有何不同?
|
6月前
|
消息中间件 Web App开发 JavaScript
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
137 0
|
2月前
|
JavaScript 开发者
深入理解Node.js事件循环及其在后端开发中的应用
【8月更文挑战第57天】本文将带你走进Node.js的事件循环机制,通过浅显易懂的语言和实例代码,揭示其背后的工作原理。我们将一起探索如何高效利用事件循环进行异步编程,提升后端应用的性能和响应速度。无论你是Node.js新手还是有一定经验的开发者,这篇文章都能给你带来新的启发和思考。
|
6月前
|
Web App开发 JavaScript 前端开发
浏览器与Node.js事件循环:异同点及工作原理
浏览器与Node.js事件循环:异同点及工作原理
|
2月前
|
JavaScript API 数据库
深入理解Node.js事件循环及其在后端开发中的应用
【9月更文挑战第3天】本文将深入浅出地介绍Node.js的事件循环机制,探讨其非阻塞I/O模型和如何在后端开发中利用这一特性来处理高并发请求。通过实际的代码示例,我们将看到如何有效地使用异步操作来优化应用性能。文章旨在为读者揭示Node.js在后端开发中的核心优势和应用场景,帮助开发者更好地理解和运用事件循环来构建高性能的后端服务。
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的图像识别技术深入理解Node.js事件循环及其在后端开发中的应用
【8月更文挑战第27天】本文将介绍深度学习中的图像识别技术,包括其原理、应用领域及未来发展。我们将探讨如何通过神经网络实现图像识别,并分析其在医疗、交通等领域的应用。最后,我们将展望图像识别技术的发展前景。
|
3月前
|
运维 Cloud Native JavaScript
云端新纪元:云原生技术深度解析深入理解Node.js事件循环及其在异步编程中的应用
【8月更文挑战第27天】随着云计算技术的飞速发展,云原生已成为推动现代软件开发和运维的关键力量。本文将深入探讨云原生的基本概念、核心价值及其在实际业务中的应用,帮助读者理解云原生如何重塑IT架构,提升企业的创新能力和市场竞争力。通过具体案例分析,我们将揭示云原生技术背后的哲学思想,以及它如何影响企业决策和操作模式。
|
3月前
|
JavaScript 前端开发
深入理解Node.js事件循环及其对后端性能的影响
【8月更文挑战第31天】 本文将带你一探Node.js的核心概念—事件循环,揭示其工作原理及如何影响后端应用的性能。我们将从基础的事件驱动模型出发,通过代码示例和性能分析,展示如何有效利用事件循环来提升应用响应速度和处理能力。
|
3月前
|
JavaScript 前端开发 API
深入理解Node.js事件循环及其在后端开发中的应用
【8月更文挑战第29天】本文将深入浅出地介绍Node.js事件循环机制,并结合代码示例探讨其如何影响后端开发实践。我们将从事件循环的基本概念出发,逐步解析其工作原理和性能优化策略,旨在帮助开发者更好地理解和运用Node.js进行高效的后端开发。
|
4月前
|
JavaScript API 调度
深入理解Node.js事件循环及其在后端开发中的应用
【7月更文挑战第30天】本文旨在通过深入浅出的方式,解析Node.js事件循环机制的工作原理及其在后端开发中的实际应用。我们将从事件循环的基本概念出发,逐步探讨其与异步I/O操作的关系,以及如何利用事件循环优化后端性能和处理高并发请求。文章将结合实际案例,为读者提供清晰的认识和应用策略。