首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

带你详细了解 Node.js 中的事件循环

Node.js 中事件循环的定义与实现均来自于 Libuv。 Libuv 围绕事件驱动的异步 I/O 模型而设计,最初是为 Node.js 编写的,提供了一个跨平台的支持库。...事件循环的六个阶段 当 Node.js 启动时,它会初始化事件循环,处理提供的脚本,同步代码入栈直接执行,异步任务(网络请求、文件操作、定时器等)在调用 API 传递回调函数后会把操作转移到后台由系统内核处理...这个阶段检查是否有到期的定时器函数,如果有则执行到期的定时器回调函数,和浏览器中的一样,定时器函数传入的延迟时间总比我们预期的要晚,它会受到操作系统或其它正在运行的回调函数的影响。...Node.js 中的事件循环在每一个阶段执行后,都会检查微任务队列中是否有待执行的任务。...特别的 process.nextTick() Node.js 中还有一个异步函数 process.nextTick(),从技术上讲它不是事件循环的一部分,它在当前操作完成后处理。

2.2K30
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    每天10个前端小知识 【Day 12】

    ,同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。...也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。 在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内部与外部连接起来的一座桥梁。...Promise,译为承诺,是异步编程的一种解决方案,比传统的解决方案(回调函数)更加合理和更加强大 在以往我们如果处理多层异步操作,我们往往会像下面那样编写我们的代码: doSomething(function...当我们遇到异步函数执行的时候,将函数执行权转移出去,当异步函数执行完毕的时候我们再将执行权给转移回来。因此我们在 generator 内部对于异步操作的方式,可以以同步的顺序来书写。...一般有以下几种方式: defer 属性: 给 js 脚本添加 defer 属性,这个属性会让脚本的加载与文档的解析同步解析,然后在文档解析完成后再执行这个脚本文件,这样的话就能使页面的渲染不被阻塞。

    13710

    深入研究 Node.js 的回调队列

    这个规则影响了事件循环和队列在 Node.js 中的工作方式。 让我们简要地看一下 Node.js 是怎样处理异步操作的。...调用栈,事件循环和回调队列 调用栈被用于跟踪当前正在执行的函数以及从何处开始运行。当一个函数将要执行时,它会被添加到调用堆栈中。这有助于 JavaScript 在执行函数后重新跟踪其处理步骤。...如你所见,在 IO 和计时器队列中,所有与异步操作有关的内容都被移交给了异步函数。 但是 promise 不同。...在 promise 中,初始变量存储在 JavaScript 内存中(你可能已经注意到了)。 异步操作完成后,Node.js 会将函数(附加到 Promise)放在微任务队列中。...每个异步函数都由依赖操作系统内部函数工作的 Node.js 去处理。 Node.js 负责将回调函数(通过 JavaScript 附加到异步操作)添加到回调队列中。

    3.8K10

    JavaScript是如何工作的:事件循环和异步编程的崛起+ 5种使用 asyncawait 更好地编码方式!

    JavaScript程序的构建块 你可能在单个.js文件中编写 JavaScript 应用程序,但可以肯定的是,你的程序由几个块组成,其中只有一个正在执行,其余的将在稍后执行。最常见的块单元是函数。...实际上,JS引擎并不是单独运行的——它是在一个宿主环境中运行的,对于大多数开发人员来说,宿主环境就是典型的web浏览器或Node.js。...这样的迭代在事件循环中称为(tick)标记,每个事件只是一个函数回调。 ? 让我们“执行”这段代码,看看会发生什么: 1.初始化状态都为空,浏览器控制台是空的的,调用堆栈也是空的 ?...注意:因为Promise 一旦被解析,它在外部是不可变的,所以现在可以安全地将该值传递给任何一方,因为它不能被意外地或恶意地修改,这一点在多方遵守承诺的决议时尤其正确。...当这个函数返回一个值时,这个值只是一个普通值而已,这个函数内部将自动创建一个承诺,并使用函数返回的值进行解析。当这个函数抛出异常时,Promise 将被抛出的值拒绝。

    3.1K20

    Node.js的事件循环(Event loop)、定时器(Timers)和 process.nextTick()

    事件循环解析 在 Node.js 启动的时候,一步步地做了:初始化事件循环,处理可能包含异步 API 调用的输入脚本(用户代码)(或进入 REPL,这里不讲 REPL),调度定时器,或者调用 process.nextTick...在事件循环的每次运行之间, Node.js 会检查是否在等待任何异步 I/O 或定时器,如果两个都没有就自动关闭。...注:为了防止轮询阶段独占事件循环而使得其它阶段一直无法被执行, libuv (一个 实现了 Node.js 事件循环机制和所有异步行为的 C 库)在停止对更多事件的轮询之前也有一个依赖于系统的最大值。...为何 process.nextTick() 还存在 为什么像这样的一个方法还存在于 Node.js 中呢?一部分是因为这是一种设计理念,即 API 即使在不需要的地方也应该始终是异步的。...另一个例子是运行一个继承了 EventEmitter 的构造函数,且想要在构造函数中调用一个事件: const EventEmitter = require('events'); const util

    1.5K30

    EventLoop 系列 - 单线程、调用栈、堆、队列、Eventloop 这些概念了解下~

    在 《JavaScript 异步编程指南》的上个模块中,我主要讲解了异步编程的基本应用,在这个模块系列中我想来聊聊事件循环,英文称为 EventLoop。...我想以一种自己理解的角度来讲,所以上来不会直接去讲浏览器中的 EventLoop 或 Node.js 中的 EventLoop。...事件循环中的一些概念,无论是在浏览器或 Node.js 中我们去学习事件循环时,这些都是通用的,了解这些概念对于后面的学习也会相对轻松些。...此时 intro() 函数中没有在调用其它函数了,按照栈的后进先出的规则,intro() 函数开始执行直到完成第二个帧从栈中弹出,之后开始执行 hello() 函数,执行完毕之后,第一个帧从栈中弹出,栈也就被清空了...堆 JavaScript 在执行时所有的数据会存放在内存里,像函数、函数变量、参数等这些已知数据占用空间的存在于内存区域的栈中,代码执行过程中创建的对象,存在于堆中,也是内存中的另外一块区域。

    1K30

    『1W7字中高级前端面试必知必会』终极版

    在 Node.js 标准库中使用 libuv 的同步方法是最常用的 阻塞 操作。原生模块中也有 阻塞 方法。...在每次运行的事件循环之间,Node.js 检查它是否在等待任何异步 I/O 或计时器,如果没有的话,则完全关闭。 process.nextTick() :它是异步 API 的一部分。...Libuv Libuv 是一个跨平台的异步 IO 库,它结合了 UNIX 下的 libev 和 Windows 下的 IOCP 的特性,最早由 Node.js 的作者开发,专门为 Node.js 提供多平台下的异步...递归 递归(英语:Recursion),又译为递回,在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。 例如: 大雄在房里,用时光电视看着未来的情况。...电视画面中的那个时候,他正在房里,用时光电视,看着未来的情况。

    80620

    50道JavaScript详解面试题,你需要了解一下

    答案,是B,因为异步函数在JavaScript中返回Promises 。 8、等待关键字会阻止应用程序中的所有JavaScript代码执行,直到返回等待的Promises?...以下语法是有效的,因为我们正在将异步函数的返回值传递给callback。 11、typeof和instanceof之间没有什么区别? typeof返回类型, instanceof返回布尔值。...不可以,因为字符串在JavaScript中是不可变的,指向字符串的变量可以分配给另一个字符串。 21、承诺链中的嵌套捕获可以捕获在承诺链中向上抛出的错误吗?...控制台输出将为'Mohit',因为内部函数有权访问在外部作用域中声明的变量。 27、函数引用自身进行递归的三种方式是什么?...控制台输出将为10和5,因为该函数在Promise中没有异步的内容,并且Promise同步解析。 32、在浏览器下一次重画显示内容之前,哪个函数会执行指定的代码块?

    3.5K40

    JavaScript 运行机制详解:再谈Event Loop

    只要栈中的代码执行完毕,主线程就会去读取"任务队列",依次执行那些事件所对应的回调函数。 执行栈中的代码(同步任务),总是在读取"任务队列"(异步任务)之前执行。请看下面这个例子。...根据上图,Node.js的运行机制如下。 (1)V8引擎解析JavaScript脚本。 (2)解析后的代码,调用Node API。 (3)libuv库负责Node API的执行。...令人困惑的是,Node.js文档中称,setImmediate指定的回调函数,总是排在setTimeout前面。实际上,这种情况只发生在递归调用的时候。...事实上,这正是Node.js 10.0版添加setImmediate方法的原因,否则像下面这样的递归调用process.nextTick,将会没完没了,主线程根本不会去读取"事件队列"!...process.nextTick(function foo() { process.nextTick(foo); }); 事实上,现在要是你写出递归的process.nextTick,Node.js

    1.1K70

    浏览器和Node.js的EventLoop事件循环机制知多少?

    如果为空,就从事件执行队列中添加到调用栈中;如果不为空,则优先执行当前调用栈中的代码。 在EventLoop中,每次循环称为一次tick。...主要顺序是: 执行栈选择最先进入队列的宏任务,执行其同步代码直到结束 检查是否有微任务,如果有则执行知道微任务队列为空 如果是在浏览器端,那么基本要渲染页面 开始下一轮的循环tick,执行宏任务中的一些异步代码...微任务 微任务是一个需要异步执行的函数,执行时机是在主函数执行完毕后、当前宏任务结束前。...如果递归调用Process.nextTick可能会导致一个无限循环,需要去适当的时机终止递归。...为什么Process.nextTick这样的API会被允许存在于Nodejs中呢? 部分原因是因为设计理念,在nodejs中api总是异步的,即使那些不需要异步的地方。

    1.7K20

    Node 10 新功能概览(译)

    它旨在将Addons与基础JavaScript引擎中的更改隔离,并允许为一个版本编译的模块在更高版本的Node.js上运行,而无需重新编译。...之前在Node 8中实验性地引入了N-API,并将从Node 10开始稳定。在Node版本之间升级不再会引起模块损坏。 它也将向后移植以实现Node.js v6.x和v8.x的兼容性。...对于浏览器而言,Chrome 66 提供的V8 Engine v6.6在JavaScript的解析和编译时间方面可以减少约20-40%。...将ESM集成到Node中并不是一个完全平滑的路径,因为它与当前系统冲突。 然而,对齐的能力是非常重要的,Node正在努力提供解决方案。...以前这些函数通过回调处理异步操作,但可以使用Node 8附带的util.promisify()函数进行转换。现在,开发人员可以在不需要额外步骤的情况下使用带有promise的fs。

    68530

    JavaScript执行机制

    在JavaScript中任务大致上分为两种任务:同步任务:可以等同与无异步逻辑的异步任务。顺序执行,与其他语言的同步任务相同。...注意: 因为微任务自身可以入列更多的微任务,且事件循环会持续处理微任务直至队列为空,那么就存在一种使得事件循环无尽处理微任务的真实风险。如何处理递归增加微任务是要谨慎而行的。...Node.js采用V8作为js的解析引擎,而I/O处理方面使用了自己设计的libuv,libuv是一个基于事件驱动的跨平台抽象层,封装了不同操作系统一些底层特性,对外提供统一的API,事件循环机制也是它里面的实现...在每次事件循环运行之间,Node.js 会检查它是否正在等待任何异步 I/O 或 timers,如果没有,则将其干净地关闭。...为了防止 轮询 阶段饿死事件循环,libuv(实现 Node.js 事件循环和平台的所有异步行为的 C 函数库),在停止轮询以获得更多事件之前,还有一个硬性最大值(依赖于系统)。

    39933

    AsyncAwait 语法简介

    如果你对JavaScript中的承诺及其与代码的关系不太熟悉,它们基本上用于表示异步函数的最终调用/成功/失败。异步函数或操作是不在解释时运行的函数,可以与其他操作并行运行。...承诺的结构与函数的体结构相同,但我们可以在函数调用的末尾使用`.then`来指定对承诺的返回值进行的下一步操作。...在处理错误时,需要确保通过处理承诺解析可能出现的错误来保证良好的开发体验。...随之而来的是在这些块中使用`await`关键字,告诉我们的程序在等待承诺解析时将其分配给一个变量,这也消除了对多个承诺使用`Promise.all`的必要。...总的来说,两者之间有一些细微的差别,但学会它们可以节省潜在的时间浪费和可能带来的巨大承诺链头痛。我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

    20810

    JS在浏览器和Node下是如何工作的?

    .'); } function bar() { baz(); } function foo() { bar(); } foo(); 上例中,我们在 baz 函数中抛出错误,则 JS 会打印以下堆栈追踪...,是 栈一旦为空的时候 稍倾,栈将会执行 callback 回调函数 下面来看看当我们具体使用 setTimeout Web API 时,所有事情是如何一步接一步工作的。...setTimeout Web API 通常用来执行一些若干秒钟之后执行的事情,该执行过程发生在程序中的所有代码都完事那一刻(栈一旦为空的时候)。...在 Node.js 中会怎样 当同样的事情发生在 Node.js 中时,就得做的更多些了 -- 因为 node 所承诺的能力也更强。在浏览器中,我们被能在后台做什么掣肘。...这就是为什么 Node.js 号称是 非阻塞事件驱动异步 I/O 架构 的原因了。

    2.1K10

    Event Loop(node.js)

    对应的异步操作是不等待结果就继续执行后面代码的操作。一般异步操作都带有一个回调函数,而回调函数里的操作不包括在上面说的「后面代码」里,而是异步操作完成以后希望要执行的操作,它们需要排队等待被执行。...异步操作的回调函数排队等待被执行就算在事件循环这一阶段。...在执行完所有同步代码以后,Node.js 查看回调队列里有没有任务,有的话就执行,没有的话就等待异步操作完成,因为带有回调任务的异步操作完成时会将回调任务入队到回调队列,这样就有任务可以执行了。...所以可以很自然地推理出,如果回调队列为空且没有需要等待完成的异步操作,这个 Node.js 进程就结束了。事实也是如此。 由上也可以知道,所有的用户代码最终都是在同一线程也就是主线程上面顺序执行的。...执行逻辑大概如下图: image.png 事件循环阶段间隙图 显然在递归调用 process.nextTick() 或 Promise.resolve() 的时候任务队列一直不为空则会引起阻塞,

    81920

    JS 事件循环 Node 篇

    所以咧,在poll阶段event loop会有一个检查机制,检查timer队列是否为空,如果timer队列非空,event loop就开始下一轮事件循环,即重新进入到「timers阶段」。...process.nextTick process.nextTick 的意思就是定义出一个异步动作,并且让这个动作在事件循环当前阶段结束后执行。...在事件循环的任何阶段,如果nextTickQueue不为空,都会在当前阶段操作结束后优先执行nextTickQueue中的回调函数,当nextTickQueue中的回调方法被执行完毕后,事件循环才会继续向下执行...此外,当有递归的异步操作时只能使用setlmmediate,不能使用process.nextTick,前面已经展示过了递归调用nextTick会出现的错误,下面使用setlmmediate来试试看: function...总结 Node.js 的事件循环分为6个阶段 浏览器和Node 环境下,microtask任务队列的执行时机不同 Node.js中,microtask 在事件循环的各个阶段之间执行 浏览器端,microtask

    2.3K10

    深度理解NodeJS事件循环

    当其中一个操作完成时,内核会告诉Node.js,以便Node.js可以将相应的回调添加到轮询队列中以最终执行。...LIBUV层: 是跨平台的底层封装,实现了 事件循环、文件操作等,是 Node.js 实现异步的核心 。...为了防止递归产生的问题, Node.js 提供了一个 process.maxTickDepth (默认 1000)。...如果没有到1ms,那么在timers阶段的时候,下限时间没到,setTimeout回调不执行,事件循环来到了poll阶段,这个时候队列为空,于是往下继续,先执行了setImmediate()的回调函数,...之后在第二个事件循环的timers阶段中再去执行相应的回调。综上所演示,我们可以总结如下:如果两者都在主模块中调用,那么执行先后取决于进程性能,也就是你的电脑好撇,当然也就是随机。

    97900

    Nodejs高并发的原理

    当其中一个操作完成时,内核会告诉Node.js,以便Node.js可以将相应的回调添加到轮询队列中以最终执行。...LIBUV层: 是跨平台的底层封装,实现了 事件循环、文件操作等,是 Node.js 实现异步的核心 。...为了防止递归产生的问题, Node.js 提供了一个 process.maxTickDepth (默认 1000)。...如果没有到1ms,那么在timers阶段的时候,下限时间没到,setTimeout回调不执行,事件循环来到了poll阶段,这个时候队列为空,于是往下继续,先执行了setImmediate()的回调函数,...之后在第二个事件循环的timers阶段中再去执行相应的回调。综上所演示,我们可以总结如下:如果两者都在主模块中调用,那么执行先后取决于进程性能,也就是你的电脑好撇,当然也就是随机。

    97050
    领券