精华内容
下载资源
问答
  • 2021-01-24 19:57:38

    nodejs事件循环机制

    nodejs是基于v8引擎的JavaScript运行时。(注意nodejs不是一门新的编程语言)

    nodejs是基于libuv实现 异步非阻塞式i/o 操作的。而事件循环是nodejs处理非阻塞式I/O操作的机制。

    以下是我理解的nodejs事件循环机制,如有问题,欢迎指正。

    首先node10+的事件循环机制与浏览器端js的事件循环机制基本一致。

    单线程or多线程

    1、nodejs的主线程是单线程,那单线程如何完成异步操作呢?

    基于底层c++ libuv库来实现。js通过V8引擎调用node API,node API底层由c++ libuv库实现,libuv库将接收到的不同异步操作分配给不同的线程,不同线程处理结束后已异步方式,将结果返回给v8引擎。

    js任务分为同步任务和异步任务,异步任务分为微任务与宏任务。

    正常js执行顺序为,执行栈中同步任务执行完毕,则执行全部微任务(清空微任务),此时主线程空闲,则执行***一次***宏任务(事件队列),继续执行执行栈,微任务队列,再执行一次宏任务。。依此反复。

    在这里插入图片描述
    1、主线程执行栈全部任务执行完毕。
    2、检查微任务队列,process.nextTick优先级最高,总是最先执行。
    3、检查宏任务队列,提取一次任务推入执行栈,进行执行。

    2、宏任务包含 setTimeout i/o setImmediate等等这么多,如果后台都已操作完成,优先执行哪一个回调呢?

    这才是事件循环的关键,特指上图右侧宏任务队列。事件循环就是为了解决异步操作。所以同步任务不属于事件循环,同时微任务也不属于事件循环的一部分。

    事件循环如图分为6个阶段,每个阶段为一个FIFO回调队列(可理解为回调函数数组),按图顺序依次执行。事件循环每进入一个阶段,则将该阶段的回调队列用尽(全部执行完毕)或到最大限制回调数,则进入下一阶段。

    举个栗子

    
    //宏任务 check阶段 暂时命名任务1
    setImmediate(()=>{
    	console.log(1)
    });
    //宏任务 timer阶段   暂时命名任务2
    setTimeout(()=>{
        console.log(2);
        //宏任务 timer阶段 暂时命名任务22
    	setTimeout(()=>{
    		console.log(22);
    	},0);
    },0);
    //宏任务 timer阶段   暂时命名任务3
    setTimeout(()=>{
    	console.log(3);
    },0);
    //宏任务 timer阶段   暂时命名任务4
    setTimeout(()=>{
    	console.log(4);
    },100);
    
    //微任务              暂时命名任务5
    process.nextTick(()=>{     
    	console.log(5);
    })
    //同步任务                 暂时命名任务6
    console.log(6);
    console.log(7);
    //执行结果为  6 7 5 2 3 1 22 4
    
    我们看以上代码
    步骤1 首先根据js执行顺序,从上到下依次执行,发现宏任务将任务放入下一个事件循环中,发现微任务,将其置入微任务队列中。将同步任务置入执行栈中。
    步骤2 开始运行执行栈,其中有两行同步语句,输出 6 7,此时执行栈中运行完毕,主线程空闲;
    步骤3 开始检查微任务队列,微任务队列中包含 process.nextTick,则输出5,微任务队列执行全部执行完毕,队列中再无其他微任务,则检查宏任务队列开始进行事件循环。
    步骤4 事件循环进入第一阶段(timer阶段),检查是否有定时器超时的回调,此时发现队列中有两个回调(任务2和任务3回调)。
    先执行任务2回调,输出 2。发现宏任务22,则将该任务放入下一次事件循环中(同步骤1。也同时符合执行一个宏任务则继续运行执行栈和微任务的解释)。
    步骤5 任务2回调执行完毕,继续执行任务3回调。 (注意所有异步操作是后台操作完成可以触发回调函数时,才将回调函数放入对应阶段的队列中。所以此时timer队列中并无任务4回调)
    步骤6 timer队列清空,事件循环进入下一阶段,依次到check阶段之前均为空队列,进入check阶段,执行任务1回调,输出1。继续进入close callback阶段。结束本次事件循环。
    步骤7 进入下一个事件循环,timer阶段,队列中任务22回调,输出22。继续进入下面阶段,直到循环结束。
    继续进入下一循环。。直到任务4超时回调触发 输出 4。

    人生第一篇原创技术博文!

    参考地址:
    https://nodejs.org/zh-cn/docs/guides/event-loop-timers-and-nexttick/
    https://www.cnblogs.com/linzhanfly/p/9082895.html

    更多相关内容
  • Event Loop事件循环机制 事件循环机制(Event Loop)是全面了解javascript代码执行顺序绕不开的一个重要知识点。 为什么会有事件循环机制? javascript从诞生之日起就是一门单线程的非阻塞的脚本语言。这是由其最初...
  • 主要介绍了JS浏览器事件循环机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要介绍了JS事件循环机制event loop宏任务微任务原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Android消息循环机制源码 前言: 搞Android的不懂Handler消息循环机制,都不好意思说自己是Android工程师。面试的时候一般也都会问这个知识点,但是我相信大多数码农肯定是没有看过相关源码的,顶多也就是网上搜搜,...
  • js事件循环机制

    2021-06-17 16:54:35
    JavaScript 事件循环机制 所有的任务队列可以分为同步任务和异步任务。同步任务会进入主线程中执行;异步任务回通过任务队列(Event Queue)的机制进行协调执行 同步和异步分别进入不同的执行环境。同步的进入...

    JavaScript 事件循环机制

    所有的任务队列可以分为同步任务和异步任务。同步任务会进入主线程中执行;异步任务回通过任务队列(Event Queue)的机制进行协调执行

    1. 同步和异步分别进入不同的执行环境。同步的进入主线程,即主行栈,异步的进入到 Event Queue。主线程内的执行完毕后,会去Event Queue 读取对应的任务,推入主线程执行。上述过程的不断重复就是 Event Loop(事件循环)。
      在这里插入图片描述
    2. 在事件循环中,每进行一次循环操作称为 tick,其关键步骤可以总结如下

    在这里插入图片描述

    • 在此次 tick 中选择最先进入队列的任务 ( oldest task ),如果有则执行(一次)
    • 检查是否存在 Microtasks,如果存在则不停地执行,直至清空 Microtask Queue
    • 更新 render
    • 主线程重复执行上述步骤
    ① task 分为两大类:分别是 Macro Task(宏任务)和 Micro Task(微任务),并且每个宏任务结束之后,都要清空所有的微任务,Macro Task 也就是常说的 Task
    
    ② Macro Task 主要包括:script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、setImmediate(Node环境)
    
    ③ Micro Task 主要包括:Promise、MutaionObserver、process.nextTick(Node环境)
    
    ④ setTimeout / Promise 等API便是任务源,而进入任务队列的是由他们指定的具体执行任务。来自不同任务源的任务会进入不同的任务队列。其中 setTimeout 和 setInterval 是同源的。
    
    1. 代码示例
    console.log('script start');
    
    setTimeout(()=>{
        console.log('timeout')
    }, 0);
    
    Promise.resolve().then(()=>{
        console.log('promise1')
    }).then(()=>{
        console.log('promise2')
    });
    
    console.log('script end');
    

    ① 整体 script 作为第一个宏任务进入主线程,遇到 console.log,输出 script start
    ② 遇到 setTimeout, 其回调函数被分发到宏任务 Event Queue 中
    ③ 遇到 pormise,其 then 函数被分到微任务 Event Queue 中,记为 then1,之后又遇到 then 函数,将其分到微任务 Event Queue中,记为 then2
    ④ 遇到 console.log,输出 script end

    1. 总结

    从规范上来看,Microtask 优先于 task 执行,所以如果有需要优先执行的逻辑,放入 Microtask队列会比 Macro Task 更早的执行

    javascript 是一门单线程语言,异步操作都是放在了事件循环队列里面,等待主线程来执行,并没有专门的异步执行线程

    展开全文
  • 浏览器的事件循环机制

    千次阅读 2021-10-01 22:08:56
    要想在线程运行过程中,能接收并执行新的任务,就需要采用事件循环机制,如果需要接收其他进程发送来的任务需要引入消息队列 渲染进程的主线程和子线程之间是子线程将任务添加到消息队列。 其他进程发送来的任务是...

    每个渲染进程都有一个主线程,并且主线程非常繁忙,既要处理 DOM,又要计算样式,还要处理布局,同时还需要处理 JavaScript 任务以及各种输入事件。要让这么多不同类型的任务在主线程中有条不紊地执行,这就需要一个系统来统筹调度这些任务,这个统筹调度系统就是我们今天要讲的消息队列事件循环系统

    一、事件循环
    所谓的事件循环机制其实可以这么理解,当 JS 引擎去执行 JS 代码的时候会从上至下按顺序执行,当遇到异步任务的,就会交由浏览器的其他线程去执行,如果是setTimeout/setInterval 定时异步任务,浏览器的渲染进程就会开一个定时器触发线程去执行,当定时时间一到,就会通知事件触发线程将定时器的回调方法推送至事件任务队列的一个宏任务队列的列尾,等待 JS 引擎执行完同步任务后,再从事件任务队列中从头取出要执行的回调方法。其他异步任务也是这么一个流程。这就是所谓的 事件循环。

    要想在线程运行过程中,能接收并执行新的任务,就需要采用事件循环机制,如果需要接收其他进程发送来的任务需要引入消息队列

    渲染进程的主线程和子线程之间是子线程将任务添加到消息队列。
    其他进程发送来的任务是渲染进程的I/O线程接收其他进程的消息,然后添加到消息队列,由主线程的事件循环系统执行。

    消息队列机制并不是太灵活,为了适应效率和实时性,引入了微任务。

    消息队列的内容为宏任务,每一个宏任务都会有一个自己的微任务队列,执行完一个宏任务之后不会马上去执行下一个宏任务,而且是查看微任务队列中是否有要执行的微任务,执行完微任务再去执行下一个宏任务。

    在这里插入图片描述

    二、执行顺序原链接
    event loop它的执行顺序:

    一开始整个脚本作为一个宏任务执行
    执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列
    当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完
    执行浏览器UI线程的渲染工作
    检查是否有Web Worker任务,有则执行
    执行完本轮的宏任务,回到2,依此循环,直到宏任务和微任务队列都为空

    微任务包括:MutationObserver、Promise.then()或catch()、Promise为基础开发的其它技术,比如fetch API、V8的垃圾回收过程、Node独有的process.nextTick。
    宏任务包括:script 、setTimeout、setInterval 、setImmediate 、I/O 、UI rendering。
    注意⚠️:在所有任务开始的时候,由于宏任务中包括了script,所以浏览器会先执行一个宏任务,在这个过程中你看到的延迟任务(例如setTimeout)将被放到下一轮宏任务中来执行。

    三、事件循环的例子原链接
    如果我们在浏览器控制台中运行’foo’函数,是否会导致堆栈溢出错误?

    	function foo() {
    	  setTimeout(foo, 0); // 是否存在堆栈溢出错误?
    	};
    

    答案是不会溢出,原因与浏览器的时间循环机制有关

    当我们说“浏览器是 JS 的家”时我真正的意思是浏览器提供运行时环境来执行我们的JS代码。
    浏览器的主要组件包括调用堆栈,事件循环**,任务队列和Web API**。 像setTimeout,setInterval和Promise这样的全局函数不是JavaScript的一部分,而是 Web API 的一部分。 JavaScript 环境的可视化形式如下所示:
    在这里插入图片描述
    事件循环(Event loop)不断地监视任务队列(Task Queue),并按它们排队的顺序一次处理一个回调。每当调用堆栈(call stack)为空时,Event loop获取回调并将其放入堆栈(stack )(箭头3)中进行处理。请记住,如果调用堆栈不是空的,则事件循环不会将任何回调推入堆栈。

    所以这个就是为什么加了setTimeout之后不会出现栈溢出的情况。

    另外还有个问题
    就是如何解决下面这个代码栈溢出的情况

    	function runStack (n) {
    	  if (n === 0) return 100;
    	  return runStack( n- 2);
    	}
    	runStack(50000)
    

    除了使用setTimeout外,在一个大佬那看到可以使用一个蹦床函数来解决

    	function runStack (n) {
    	  if (n === 0) return 100;
    	  return runStack.bind(null, n- 2); // 返回自身的一个版本
    	}
    	// 蹦床函数,避免递归
    	function trampoline(f) {
    	  while (f && f instanceof Function) {
    	    f = f();
    	  }
    	  return f;
    	}
    	trampoline(runStack(1000000))
    

    这个代码就类似于调用一个函数,先把trampoline函数压入到方法调用栈中,然后执行trampoline函数中代码的时候需要调用runStack函数,然后又把runStack压入到函数调用栈中,runStack执行完之后又马上将其弹出栈,因此不会出现栈内有很多函数的情况,所以不会出现栈溢出。

    展开全文
  • 给大家分享了关于JavaScript事件循环机制的相关知识点内容,有兴趣的朋友们可以学习参考下。
  • 主要介绍了提升Python效率之使用循环机制代替递归函数的相关知识,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 一、浏览器JS异步执行的原理 一般常说js是一门单线程语言,那为什么可以异步执行...二、事件循环机制 1 - 执行栈和任务队列 (1)执行栈是什么 用于按执行顺序存放同步代码 按序执行,执行完毕后弹出执行栈 如果在执

    一、浏览器JS异步执行的原理

    一般常说js是一门单线程语言,那为什么可以异步执行且不发生阻塞呢?

    • 常说的JS是单线程语言,是因为执行JS的引擎是单线程的,而浏览器本身是多线程的
    • 浏览器主要含有:
      • js 执行线程
      • 定时器线程
      • http 请求线程
      • 事件触发线程
      • GUI 线程等
    • 异步请求的真正执行者是浏览器的其他线程
    • js 引擎只是执行了异步操作成功了之后的回调函数

    二、事件循环机制

    1 - 执行栈和任务队列

    (1)执行栈是什么

    • 用于按执行顺序存放同步代码
    • 按序执行,执行完毕后弹出执行栈
    • 如果在执行过程中遇到异步操作,就交给其他线程处理

    (2)任务队列

    • 用于按序排放异步操作执行结束后的回调函数
    • 任务队列中的函数等待执行栈执行结束后取出执行

    2 - 事件循环的本质

    • 基于事件驱动模式
    • 至少包含了一个事件循环来判断当前的任务队列是否有新的任务
    • 通过不断的循环取出异步回调进行执行

    3 - 宏任务和微任务

    (1)宏任务的分类

    • 渲染事件
    • 用户交互事件
    • SetTimeout、setInterval
    • 网络请求、文件读写等

    有明确异步操作的任务,需要其他的异步线程支持

    (2)微任务的分类

    • promise.then promise.catch
    • process.nextTick

    没有明确的异步任务需要执行,只有回调不需要其他异步线程的支持

    (3)执行顺序

    • 在同步代码执行结束后
    • 先执行微任务队列中的微任务
    • 再执行宏任务队列中的宏任务

    (4)案例

    console.log('同步代码1');
    setTimeout(() => {
        console.log('setTimeout')
    }, 0)
    new Promise((resolve) => {
      console.log('同步代码2')
      resolve()
    }).then(() => {
        console.log('promise.then')
    })
    console.log('同步代码3');
    
    // 最终输出"同步代码1"、"同步代码2"、"同步代码3"、"promise.then"、"setTimeout"
    
    setTimeout(() => {
      console.log('setTimeout start');
      new Promise((resolve) => {
        console.log('promise1 start');
        resolve();
      }).then(() => {
        console.log('promise1 end');
      })
      console.log('setTimeout end');
    }, 0);
    function promise1() {
      return new Promise((resolve) => {
        console.log('promise2');
        resolve();
      })
    }
    async function async1() {
      console.log('async1 start');
      await promise1();
      console.log('async1 end');
    }
    async1();
    console.log('script end');
    
    // 输出结果
    async1 start
    promise2
    script end
    async1 end
    setTimeout start
    promise1 start
    setTimeout end
    promise1 end
    

    4 - 定时器误差

    (1)执行顺序

    • 遇到一个定时器请求,开启定时器线程去计时
    • 计时结束后将回调函数放入到任务队列(宏任务)
    • 等待同步任务执行 waiting… ,在同步任务执行结束后可能还有微任务
    • 同步任务执行结束后取出任务队列中的回调

    (2)误差大小

    • 定时器的误差值取决于同步任务的执行时间 + 微任务的执行时间
    • 同步任务执行时间越长,定时器的误差越大

    三、脑图总结

    在这里插入图片描述

    展开全文
  • js事件循环机制(Event Loop)

    千次阅读 2022-02-11 09:50:06
    }) fn() console.log(3) promise.then(() => { console.log(12) }) function fn(){ console.log(6) } 结果是1、4、6、3、12、8、2、11、10、9、7 这个写法可以囊括80%以上的event loop循环机制的场景了,下面开始...
  • 带你了解事件循环机制(Event Loop)

    千次阅读 2021-08-18 20:33:20
    什么是事件循环机制? 事件循环分为两种,分别是浏览器事件循环和node.js事件循环,本文主要对浏览器事件循环进行描述。 我们都知道JavaScript是一门单线程语言,指主线程只有一个。Event Loop事件循环,其实就是JS引擎...
  • 主要介绍了js事件循环机制,并通过实例分析了用法和技巧,一起学习分享下。
  • Node.js 事件循环机制

    2022-03-13 16:40:39
    目录事件循环机制回调 事件循环机制 事件循环机制(Event Loop) JavaScript为单线程,怎样处理任务 处理安排好的任务,按照顺序写进主线程里,等线程执行时,这些任务就是 按照顺序在线程中依次被执行;等所有任务...
  • 事件循环机制EventLoop

    千次阅读 2020-05-19 21:48:47
    事件循环机制EventLoop Event Loop即事件循环,是解决javaScript单线程运行阻塞的一种机制。 一、EventLoop的相关概念 1、堆(Heap) 堆表示一大块非结构化的内存区域,对象,数据被存放在堆中 2、栈(Stack) 栈在...
  • JavaScript 事件循环机制(Event Loop)简述 单线程的 JavaScript Web Worker 任务队列 运行机制 事件回调 事件循环(Event Loop) 单线程的 JavaScript JavaScript 是浏览器的脚本语言。其主要作用是与客户端...
  • JS浏览器事件循环机制

    千次阅读 2020-05-29 17:16:22
    JavaScript 事件循环机制 JavaScript 事件循环机制分为: 浏览器和 Node 事件循环机制, 两者的实现技术不一样: 浏览器 Event Loop 是 HTML 中定义的规范, Node Event Loop 是由 libuv 库实现。 这里主要讲的是...
  • QT消息/事件循环机制

    千次阅读 2020-12-18 09:38:25
    一、QT消息/事件循环机制 Qt作为一个可视化GUI界面操作系统,是基于事件驱动的,我们程序执行的顺序不再是线性,而是由一个个应用程序内部或外部的事件进行驱动,无事件时便阻塞。这个循环概念类似于while的函数循环...
  • 浏览器事件循环机制

    千次阅读 2020-06-13 21:53:33
    main()、printSqaure(4)、square(n)、mutltiply(n,n)依次入栈 mutltiply(n,n)、square(n)、printSqaure(4)、main()依次出栈 最终控制台会输出最终结果:8 浏览器执行JavaScript时,事件循环可以保证这个线程可以...
  • js的事件循环机制比较简单 先执行主线程代码,执行完毕后,清空微任务队列,然后取出一个宏任务,然后清空微任务队列,如此循环 Node的事件循环比较复杂  Node的事件循环分为六个阶段 (1)timers计时器 执行...
  • 彻底搞懂JS事件循环机制(event loop)

    千次阅读 多人点赞 2020-12-31 14:47:48
    提一嘴规则其实没有0 最低按4ms处理 EventLoop 所谓事件环,就是三步不断循环的js的执行闭环 同步主线程 异步函数放入eventTable注册,等待完成后放入eventQueue 同步主线程完成,取eventQueue放入主线程 宏任务...
  • 胸水的循环机制PPT学习教案.pptx
  • 面试题:说说事件循环机制(满分答案来了)

    万次阅读 多人点赞 2020-03-09 08:45:00
    答题大纲先说基本知识点,宏任务、微任务有哪些说事件循环机制过程,边说边画图出来说async/await执行顺序注意,可以把 chrome 的优化,做法其实是违反了规范的,V8 团队的PR...
  • 然后介绍了嵌入式应用级同步调试模型并指出此模型在多线程应用程序调试中的不足,接着引入事件循环机制,并在事件循环机制的基础之上实现异步多线程应用级调试模型;最后通过实验验证使用异步非即停调试模式进行应用级...
  • JS的事件循环机制

    2020-06-17 16:57:24
    JS的事件循环机制 事件执行的顺序 当事件开始时,首先会进入JS主线程机制,由于JS属于单线程机制,因此存在多个任务的时候会存在等待的情况,先等待最先进入线程的事件处理完毕 这样就会出现等待的情况,如果之前的...
  • js代码-事件循环机制(1)
  • js代码-事件循环机制(2)

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 647,859
精华内容 259,143
关键字:

循环的机制