我已经迷失在事件环(event-loop)中了【Nodejs篇】

我第一次看到他事件环(event-loop)的时候,我是一脸懵,这是什么鬼,是什么循环吗,为什么event还要loop,不是都是一次性的吗?

浏览器中和nodejs环境中的事件环是有一些区别的,这里我只研究了nodejs环境,小黑框情况下的事件环。

这里的事件环并不是指单独一件事件的循环,而是我们写的很多很多的事件按照一定地规则排着队去执行,然后队列清空后继续排队,就是事件环。

事件环很复杂,这里我只有能力解释事件环中的几个点:

node.js中对于事件环的解释

nodejs中将eventloop分成了:

  • timers: 定时器setTimeout执行,将callback加入队列中。
  • pending callbacks: 一些I/O的callback,推迟到下一次循环中执行。
  • idle, prepare: 内部的一些事件。
  • poll: 定时器的callback执行,setImmediate执行,微任务执行。
  • check: setImmediate的callback执行。
  • close callbacks: 一些callbacks的关闭,如socket。

这边我们专注于timers、poll和check这三个阶段。其他的我们用的不多。

timers、poll、check阶段

  • timers

这个阶段,只执行setTimeout和setInterval,但是他们的callback不会执行,而是推到宏任务的队列之中。

  • poll

这个阶段,会先执行符合条件的微任务,比如Promise的异步完成,如果是setImmediate,则只会执行,不执行他的callback,然后执行定时器的callback,比如timeout。这里会适当得暂停一会,看看会不会有新任务进入队列。如果有setImmediate的callback则进入check 阶段,否则回到timer继续新一轮循环。

  • check

当poll阶段的队列完成,则会轮到check,这时会执行setImmediate的callback。如果没有需要关闭callbacks,那么就回到timer继续新一轮的循环。

宏任务 vs 微任务

  • 宏任务

从我的角度理解,就是一个正常的task,本来在一个线程中可以毫无波折地一个接着一个运行到最后,奈何每个宏任务执行之后都有可能产生一些微任务,因此很不幸,这些宏任务就要排在这些微任务之后了。

宏任务代表:script(整体代码),setTimeout,setImmediate。

/**
output:
我先走一步
你太慢了,我插个队
老司机,等等我
*/
setTimeout(()=>{
    console.log("我先走一步")
})
setTimeout(()=>{
    console.log("老司机,等等我")
},10)
setImmediate(()=>{
    console.log("你太慢了,我插个队")
})

划重点

setTimeout和setImmediate,触发的阶段不同,因此callback执行时间也不同。但是如果setTimeout的时间过长,那么系统会先执行setImmediate,然后等下一轮询中,如果setTimeout到时间了,那么就运行setTimeout的callbacks。

  • 微任务

就是宏任务执行时,产生的新的小任务,比如异步,此类任务称之为微任务,一般在当前宏任务执行完之后“插队”执行。

微任务代表:process.nextTick, Promise(原生)。

划重点

虽然process.nextTick和Promise都是微任务,但是他们的执行的先后顺序是不一样的。无论谁的代码先执行,等到了poll阶段,两者都是可运行的状态时,都是nextTick先于Promise执行。

/**
output:
本宫始终是你望成莫及的
总有一日,我会上位
*/
Promise.resolve().then(()=>{
    console.log("总有一日,我会上位")
})
process.nextTick(()=>{
    console.log("本宫始终是你望成莫及的")
})

后记:

我只写了我对于eventloop的理解,但是还有很多云里雾里的地方,写出来的只是我理解的。

原文地址:https://www.cnblogs.com/cherryvenus/p/9482995.html

时间: 2024-10-02 22:45:21

我已经迷失在事件环(event-loop)中了【Nodejs篇】的相关文章

node.js事件循环 event loop

Nodejs事件循环 (event loop) node.js 事件循环的概念 当node.js 启动的时候会初始化eventloop ,每一个evnet loop 都会包含如下6个循环阶段,node.js 事件循环和浏览器事件循环完全不一样. 官网文档:https://nodejs.org/zh-cn/docs/guides/event-loop-timers-and-nexttick/ timers pending callbacks (I/O callbakcs) idle, prepar

JavaScript:彻底理解同步、异步和事件循环(Event Loop) (转)

原文出处:https://segmentfault.com/a/1190000004322358 一. 单线程 我们常说"JavaScript是单线程的". 所谓单线程,是指在JS引擎中负责解释和执行JavaScript代码的线程只有一个.不妨叫它主线程. 但是实际上还存在其他的线程.例如:处理AJAX请求的线程.处理DOM事件的线程.定时器线程.读写文件的线程(例如在Node.js中)等等.这些线程可能存在于JS引擎之内,也可能存在于JS引擎之外,在此我们不做区分.不妨叫它们工作线程

JavaScript:彻底理解同步、异步和事件循环(Event Loop)

转自:https://segmentfault.com/a/1190000004322358 http://www.cnblogs.com/rubylouvre/ http://www.tuicool.com/articles/7B7Bju http://soyoung.blog.51cto.com/7578959/1550874/ http://bbs.csdn.net/topics/390765530 https://cnodejs.org/topic/52414b3a101e5745219

同步异步和Event loop事件循环

目录 js 单线程模型 js 中的栈.堆和消息队列 栈 堆 消息队列 Event Loop 什么是事件循环Event Loop 主线程 同步任务和异步任务 同步任务 异步任务 宏任务 微任务 事件循环的过程 js 单线程模型 JavaScript 是单线程.非阻塞的一种语言,只有一个主线程,同时只能执行一个任务. js 使用单线程是为了简单化 js 中的栈.堆和消息队列 栈 存放的是调用函数的记录--调用帧 堆 存放的是对象 消息队列 包含待处理消息的队列 每个消息都关联了一个回调函数,用以处理

以setTimeout来聊聊Event Loop

平时的工作中,也许你会经常用到setTimeout这个方法,可是你真的了解setTimeout吗?本文想通过总结setTimeout的用法,顺便来探索javascript里面的事件执行机制. setTimeout基本用法 1. setTimeout(code,millisec) setTimeout函数接受两个参数,第一个参数code是将要推迟执行的函数名或者一段代码,第二个参数millisec是推迟执行的毫秒数. 例如: setTimeout(‘console.log(2)’,100); se

并发模型与Event Loop

JavaScript的并发模型基于"event loop".这个模型与其他在C或者Java中的模型着实不同. 运行时概念 下面的内容解释了一个理论上的模型.现代JavaScript引擎着重实现和优化了描述的几个语义. 可视化描述 栈 函数调用形成了一个frames的栈. function f(b){   var a = 12;   return a+b+35;}function g(x){   var m = 4;   return f(m*x);}g(21); 调用g的时候,创建了第

JavaScript执行顺序Event Loop

javascript是一门单线程语言,为了实现主线程的不阻塞,但可以用Event Loop模拟多线程操作 Event Loop中同步异步任务执行顺序: 所有异步任务都是在Event Table中注册函数,当指定的时间完成时,Event Table会将函数放入Event Queue,主线程的同步任务执行完会去Event Queue读取对应函数,进入主线程执行. js引擎monitoring process进程,当发现主进程执行栈为空,会去执行Event Queue中的函数 let data = [

javascript的执行机制—Event Loop

既然今天要谈的是javascript的事件循环机制,要理解事件循环,首先要知道事件循环是什么. 我们先从一个例子来看一下javascript的执行顺序. <script> setTimeout(function() { console.log('定时器开始了.'); },0) new Promise(function(resolve) { console.log('马上执行for循环了'); for (let i = 0; i < 10000; i++) { i == 99 &&

事件轮询 event loop

Understanding the node.js event loop The first basic thesis of node.js is that I/O is expensive: So the largest waste with current programming technologies comes from waiting for I/O to complete. There are several ways in which one can deal with the