-
事件循环
2018-04-26 11:16:00几张图告诉你事件循环和Job Queue究竟是什么 JavaScript:彻底理解同步、异步和事件循环(Event Loop) JS 的线程、事件循环、任务队列简介 详解事件循环机制 什么是浏览器的事件循环(Event Loop)? 深入理解 ...转载于:https://www.cnblogs.com/yancongyang/p/8950360.html
-
nodejs事件和事件循环简介
2020-12-06 21:37:03我们在javascript中监听这些事件,从而触发相应的处理。 同样的nodejs中也有事件,并且还有一个专门的events模块来进行专门的...同时事件和事件循环也是nodejs构建异步IO的非常重要的概念。 今天我们来详细了解一下。简介
熟悉javascript的朋友应该都使用过事件,比如鼠标的移动,鼠标的点击,键盘的输入等等。我们在javascript中监听这些事件,从而触发相应的处理。
同样的nodejs中也有事件,并且还有一个专门的events模块来进行专门的处理。
同时事件和事件循环也是nodejs构建异步IO的非常重要的概念。
今天我们来详细了解一下。
事件
nodejs为事件提供了一个专门的模块:lib/events.js。
还记得我们在讲使用nodejs构建web服务器吗?
const server = http.createServer((req, res) => { res.statusCode = 200 res.setHeader('Content-Type', 'text/plain') res.end('welcome to www.flydean.com\n') })
这里,每个请求都会触发request事件。
nodejs的核心API是基于异步事件驱动来进行架构的,所以nodejs中有非常多的事件。
比如:net.Server 会在每次有新连接时触发事件,fs.ReadStream 会在打开文件时触发事件,stream会在数据可读时触发事件。
我们看一下怎么来构建一个nodejs的事件:
const EventEmitter = require('events') const eventEmitter = new EventEmitter()
events常用的方法有两个,分别是on和emit。
on用来监听事件,emit用来触发事件。
eventEmitter.on('fire', () => { console.log('开火') }) eventEmitter.emit('fire')
emit还可以带参数,我们看下一个参数的情况:
eventEmitter.on('fire', who => { console.log(`开火 ${who}`) }) eventEmitter.emit('fire', '美帝')
再看看两个参数的情况:
eventEmitter.on('fire', (who, when) => { console.log(`开火 ${who} ${when}`) }) eventEmitter.emit('fire', '川建国','now')
默认情况下,EventEmitter以注册的顺序同步地调用所有监听器。这样可以确保事件的正确排序,并有助于避免竞态条件和逻辑错误。
如果需要异步执行,则可以使用setImmediate() 或者 process.nextTick()来切换到异步执行模式。
eventEmitter.on('fire', (who, when) => { setImmediate(() => { console.log(`开火 ${who} ${when}`); }); }) eventEmitter.emit('fire', '川建国','now')
除此之外,events还支持其他几个方法:
once(): 添加单次监听器
removeListener() / off(): 从事件中移除事件监听器
removeAllListeners(): 移除事件的所有监听器
事件循环
我们知道nodejs的代码是运行在单线程环境中的,每次只会去处理一件事情。
这一种处理方式,避免了多线程环境的数据同步的问题,大大的提升了处理效率。
所谓事件循环,就是指处理器在一个程序周期中,处理完这个周期的事件之后,会进入下一个事件周期,处理下一个事件周期的事情,这样一个周期一个周期的循环。
事件循环的阻塞
如果我们在事件处理过程中,某个事件的处理发生了阻塞,则会影响其他的事件的执行,所以我们可以看到在JS中,几乎所有的IO都是非阻塞的。这也是为什么javascript中有这么多回调的原因。
事件循环举例
我们看一个简单的事件循环的例子:
const action2 = () => console.log('action2') const action3 = () => console.log('action3') const action1 = () => { console.log('action1') action2() action3() } action1()
上面的代码输出:
action1 action2 action3
栈和消息队列
我们知道函数间的调用是通过栈来实现的,上面的例子中,我们的调用顺序也是通过栈来实现的。
但并不是函数中所有的方法都会入栈,还有一些方法会被放入消息队列。
我们再举一个例子:
const action2 = () => console.log('action2') const action3 = () => console.log('action3') const action1 = () => { console.log('action1') setTimeout(action2, 0) action3() } action1()
上面的代码运行结果:
action1 action3 action2
结果不一样了。这是因为settimeout触发了定时器,当定时器到期的时候,回调函数会被放入消息队列中等待被处理,而不是放入栈中。
事件循环会优先处理栈中的事件,只有栈中没有任何数据的时候,才会去转而消费消息队列中的事件。
虽然上面例子中setTimeout的timeout时间是0,但是还是要等到action3执行完毕才能执行。
注意,setTimeout中的timeout并不是在当前线程进行等待的,它是由浏览器或者其他JS执行环境来调用的。
作业队列和promise
ES6中的Promise引入了作业队列的概念,使用作业队列将会尽快地执行异步函数的结果,而不是放在调用堆栈的末尾。
举个例子:
const action2 = () => console.log('action2') const action3 = () => console.log('action3') const action1 = () => { console.log('action1') setTimeout(action2, 0) new Promise((resolve, reject) => resolve('应该在action3之后、action2之前') ).then(resolve => console.log(resolve)) action3() } action1()
输出结果:
action1 action3 应该在action3之后、action2之前 action2
这是因为,在当前函数结束之前 resolve 的 Promise 会在当前函数之后被立即执行。
也就是说先执行栈,再执行作业队列,最后执行消息队列。
process.nextTick()
先给大家一个定义叫做tick,一个tick就是指一个事件周期。而process.nextTick()就是指在下一个事件循环tick开始之前,调用这个函数:
process.nextTick(() => { console.log('i am the next tick'); })
所以nextTick一定要比消息队列的setTimeout要快。
setImmediate()
nodejs提供了一个setImmediate方法,来尽快的执行代码。
setImmediate(() => { console.log('I am immediate!'); })
setImmediate中的函数会在事件循环的下一个迭代中执行。
setImmediate() 和 setTimeout(() => {}, 0)的功能基本上是类似的。它们都会在事件循环的下一个迭代中运行。
setInterval()
如果想要定时执行某些回调函数,则需要用到setInterval。
setInterval(() => { console.log('每隔2秒执行一次'); }, 2000)
要清除上面的定时任务,可以使用clearInterval:
const id = setInterval(() => { console.log('每隔2秒执行一次'); }, 2000) clearInterval(id)
注意,setInterval是每隔n毫秒启动一个函数,不管该函数是否执行完毕。
如果一个函数执行时间太长,就会导致下一个函数同时执行的情况,怎么解决这个问题呢?
我们可以考虑在回调函数内部再次调用setTimeout,这样形成递归的setTimeout调用:
const myFunction = () => { console.log('做完后,隔2s再次执行!'); setTimeout(myFunction, 2000) } setTimeout(myFunction, 2000)
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/nodejs-event/
本文来源:flydean的博客
欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
-
形象化解读js事件循环以及node事件循环和浏览器事件循环的区别
2020-04-28 01:12:35node和浏览器都是js运行的环境,二者都给js提供了一个很强大的功能,事件循环。那么什么是事件循环呢,简单讲就是在单线程中为了实现程序的高效运行而设定的事件执行机制 ...技术背景
javaScript事件循环(Event Loop)是其作为单线程语言但能实现高效异步运行的核心基础。要想更深入的了解js,对事件循环就要有一个清楚地认识。在node出现之后,js的运行环境不再是单一的浏览器,同样的,node中在有事件循环。那么到底什么是事件循环呢?写事件循环的文章有很多,但是对于一些初学者看起来却有些不好理解,本文试着对event loop做一个有表象到宏观的认识,希望把事件循环表述的更加形象化。首先了解几个背景问题。
几个背景问题:
1,什么是线程,进程,二者有什么区别和联系,
进程是计算机系统资源分配的最小单位,该最小单位相互之间有独立的内存,进程有独立的内存空间;
线程是计算机cpu调度分配的最小单位,调度最小单位是cpu中可以独立运行的最小基本单位,线程没有属于自己的内存空间;
一个进程可以有很多线程,每条线程并行执行不同的任务。
形象化理解:
把计算机看做一家公司
进程就是独立的部门,每个部门有自己的资源;
线程就是每个部门的员工,每个员工没有资源,是最小的干活单位,共享部门资源;
2,js为什么是单线程的
这主要和js的用途有关,在node出现之前,js是作为浏览器的脚本语言,主要是实现用户与浏览器的交互,以及操作dom;这决定了它只能是单线程,否则会带来很复杂的同步问题。
举个例子:如果js被设计了多线程,如果有一个线程要修改一个dom元素,另一个线程要删除这个dom元素,此时浏览器就会一脸茫然,不知所措...
单线程和事件循环(event loop)
javaScript是单线程的,在执行代码时只能按顺序执行,为了解决代码执行时的阻塞,所以js是异步的,比如在遇到setTimeout时,不会定时器内容执行过后,再去执行之后的代码,而是先执行代码,等时间到后再去执行定时器。
基于这种异步的机制,javaScript有着一套自己执行代码的规则,来保证代码能够高效无阻塞的运行,这种规则就是事件循环。
node和浏览器都给js提供了运行的环境,但是二者的运行机制是稍有差异的。
浏览器js运行机制
不同的浏览器有不同的js引擎
虽然浏览器不同,不过起内部的事件循环规则是一致的。
node.js运行机制
node.js采用v8作为js的解析引擎,而在I/O处理方面采用了libuv。
libuv库负责node api的执行,它将不统的任务分给不同的线程,形成一个Event Loop。以异步的方式将执行的结果返回给V8引擎。
浏览器中的Event Loop
直接用文字描述Event Loop理解起来是比较费脑的,首先先介绍下Event Loop的相关概念。
Event Loop包括了 执行栈, 事件队列, 微任务,宏任务,执行栈和事件队列是事件循环中存储事件的地址,微任务和宏任务是事件循环中执行的事件。
执行栈:
js整体代码加载过后,会进入运行,这时会产生一个执行上下文(context),当代码执行完毕之后,该执行上下文被释放。对于一个执行上下文,也可以称为当前js执行环境,包括了私有作用域,当前作用域中的变量,上层作用域,当前作用域对象this。
由于js是单线程的,在执行前面的代码时,后面的代码等待执行,此时该部分代码(函数或者可直接执行的代码)被放到一个栈中,称为执行栈。
事件队列:
上面js的运行只考虑了同步事件,当js执行过程中遇到了异步事件(或者定时事件),会把对应的这些事件挂起,js并将这个事件加入与当前执行栈不同的另一个队列,继续执行当前执行上下文中的同步代码,这个存储异步事件的队列称为事件队列。
在一个执行环境中的执行栈清空之后,js此时会去查看事件队列是否为空,不为空,则继续执行这些事件。
执行事件队列中的事件时,会遵循执行栈的规则,首先会生成一个对应当前事件的执行上下文,然后生成执行栈,事件队列,当该执行环境中的代码 执行完毕并返回结果后,js会退出这个执行环境并把这个执行环境销毁,回到上一个方法的执行环境。接着执行事件队列中的下一个事件,规则一样。当事件队列清空后,外层执行环境被销毁,执行结束。
从上面的分析中可以看出,事件循环指的是在事件队列中执行代码重复了外层执行栈的规则,一层一层深入,就形成了循环。
两个注意点:
1,同一个执行上下文中同步任务优先于异步任务
2,不同执行环境中的异步任务执行先后取决于其加入到事件队列的时间先后
3,事件队列在不同执行环境中是同一个
例子:
function a(){ console.log('a') setTimeout( () => { console.log('a1') },0) } function b(){ console.log('b') setTimeout( () => { console.log('b1') },0) } setTimeout( () => { console.log('上层') },0) a() b() // 运行结果 // a // b // 上层 // a1 // b1
改变时间
function a(){ console.log('a') setTimeout( () => { console.log('a1') },100) } function b(){ console.log('b') setTimeout( () => { console.log('b1') },0) } setTimeout( () => { console.log('上层') },10) a() b() // 运行结果 // a // b // b1 // 上层 // a1
形象化理解Event Loop:
把js代码中的方法看成是医院看病的病人,
执行栈是所有的病人,按顺序就诊
同步任务是直接就诊的病人
异步任务是需要化验的病人,拿到结果后就诊
对于循环
需要化验的病人如果是一个团体,后面排队的病人等待这个团体直接就诊的病人都看完后,就诊下一个团体,循环就诊。
微任务:
new Promise()
new MutaionObserver()
宏任务:
setInterval()
setTimeout()
- 整体代码
- I/O 操作、UI 渲染
在一个事件循环中,异步事件返回结果后会被放到一个任务队列中。然而,根据这个异步事件的类型,这个事件实际上会被对应的宏任务队列或者微任务队列中去。并且在当前执行栈为空的时候,主线程会 查看微任务队列是否有事件存在。如果不存在,那么再去宏任务队列中取出一个事件并把对应的回到加入当前执行栈;如果存在,则会依次执行队列中事件对应的回调,直到微任务队列为空,然后去宏任务队列中取出最前面的一个事件,把对应的回调加入当前执行栈...如此反复,进入循环。
总结:事件队列分为微任务队列,宏任务队列,同一次事件循环中,微任务永远在宏任务之前执行。
形象化理解:
微任务是需要化验的急诊病人
宏任务是需要化验的普通病人
node中的Event Loop
从node的运行机制我们知道,ibuv库负责node api的执行
每个阶段的含义:
- timers: 这个阶段执行定时器队列中的回调如
setTimeout()
和setInterval()
。 - I/O callbacks: 这个阶段执行几乎所有的回调。但是不包括close事件,定时器和
setImmediate()
的回调。 - idle, prepare: 这个阶段仅在内部使用,可以不必理会。
- poll: 等待新的I/O事件,node在一些特殊情况下会阻塞在这里。
- check:
setImmediate()
的回调会在这个阶段执行。 - close callbacks: 例如
socket.on('close', ...)
这种close事件的回调。
执行顺序
当个v8引擎将js代码解析后传入libuv引擎后,循环首先进入poll阶段,poll阶段相当于整体同步代码的解析,会生成一个执行栈,同时会把
setImmediate的回调放入check队列,在setTimeout()
和setInterval()定时到期后把其回调事件放入timers队列,
poll queue清空后,会转到check阶段,检查执行check队列,检查执行timer队列,之后进入到callbacks阶段,执行回调。check和timer两者的顺序是不固定的,受到代码运行的环境的影响。进入一个新阶段之后,会重复上面各个阶段,直至执行完毕,进入下一个阶段。
总结:
poll轮询属于io观察者,process.nextTick()属于idle观察者, setImmediate()属于check观察者。
在每一轮循环检查中,idle观察者先于I/O观察者,I/O观察者先于check观察者.
第一次进入代码时,idle观察者不存在。
Node中的process.nextTick()
process.nextTick()是node中一个特殊的队列,这些事件会在每一个阶段执行完毕准备进入下一个阶段时优先执行。也就是说process.nextTick()在阶段切换时执行。并且,不管其有多深的回调,都会被一次执行完毕。
Promise
上面的阶段没有包括Promise,在node中,promise和浏览器中类似,执行在process.nextTick()之后,在setTimeout之前
实例:
const fs = require('fs') const path = require('path') const wait = () => new Promise((resolove, reject) => { setTimeout(resolove(true), 3) }) fs.readFile(path.resolve(__dirname, './vue.config.js'), 'utf-8', async (err, data) => { console.log('读取的文件内容') await wait() console.log('测试测试') process.nextTick(() => { console.log('nextTick') }) }) setTimeout(() => { console.log('定时器任务0') }, 0) setTimeout(() => { console.log('定时器任务100') }, 1000) setImmediate(() => { console.log('立即执行') }) Promise.resolve().then(() => { console.log('promise') }) process.nextTick(() => { console.log('外层nextTick') }) console.log('外层同步') // 运行结果 // 外层同步 // 外层nextTick // promise // 定时器任务0 // 立即执行 // 读取的文件内容 // 测试测试 // nextTick // 定时器任务100
形象化理解
固执的探险家(每个房间都要走到底)
所有的代码就像是已经设定好的迷宫,而引擎就是去探险的人,我们称为小呆。
小呆到达迷宫,已经有了地图,根据地图冒险。
迷宫有六个房间,分别是timer, i/ocallback, ide prepare(内部使用,已封闭), poll, check, close callback,
其中timer是虚拟现实房间,小呆随时可以看到里面的场景。
其他的每个房间又五个房间,有的开放,有的不开放。
探险规则:每次离开一个房间,都要检查有没有受伤(peocess.nextTick())
小呆首先进入poll房间,开始探险(执行poll 队列),之后进入check房间,timer房间(随机),探险完之后出来,进入close callback,探险完之后,进入io/callback房间,最后完成探险,离开。
小呆说任务总算完成了。
参考:
https://zhuanlan.zhihu.com/p/33058983
https://zhuanlan.zhihu.com/p/54882306
-
Redis事件循环
2021-01-22 20:42:06事件循环的意义 Redis本身是一个事件驱动的程序,事件循环模块的稳定性和吞吐量其实在某种程度上决定了Redis响应各种请求的速度。事件循环模块非常精良的设计和实现也是Redis能用单线程(到6.0版本之前)抗住各种...目录
事件循环的意义
Redis本身是一个事件驱动的程序,事件循环模块的稳定性和吞吐量其实在某种程度上决定了Redis响应各种请求的速度。事件循环模块非常精良的设计和实现也是Redis能用单线程(到6.0版本之前)抗住各种业务场景中的大并发请求的原因之一。甚至在某种程度上可以算是最重要的原因。考虑所有的CURD请求和定时任务均需要经过该模块进行分发处理
事件循环的静态结构
如图所示,事件循环模块的静态结构如上。北向API给其他模块(内部模块或外部触发的事件)提供CUD接口,分别针对文件事件和时间事件进行操作。时间事件直接通过一个链表进行事件的管理,文件事件则是通过抽象工厂模式,由四个模块提供一个aeApiPoll函数,然后通过一段宏定义的判断选择调用哪个。
#ifdef HAVE_EVPORT #include "ae_evport.c" #else #ifdef HAVE_EPOLL #include "ae_epoll.c" #else #ifdef HAVE_KQUEUE #include "ae_kqueue.c" #else #include "ae_select.c" #endif #endif #endif
为了进一步了解,我将ae.h中定义的数据结构图的主要部分画出如下,可以看到aeEventLoop结构体中,有三个结构体,分别指向文件事件(aeFileEvent),正在处理的事件(aeFiredEvent),时间事件(aeTimeEvent),另外还有2个函数指针存储调用aeApiPoll前后要执行的函数。文件事件结构体内存储事件的读写时执行的函数,时间事件通过一个队列进行管理,所以结构体中还带有2个指针,指向前后要执行的事件。
事件循环的主流程
如图所示,这是Redis事件循环模块处理的主逻辑。Redis的进程启起来之后,用一个while不断地循环这部分的逻辑。逻辑讲述如下:
- 根据事件标记选择继续或者直接终止本次处理;
- 搜索最近的时间事件;
- 根据当前时间和时间事件的间隔,初始化一个时间结构体,作为后面处理文件事件的输入;
- 处理文件事件;
- 处理时间事件。
文件事件
如图所示,这是Redis事件循环模块处理文件事件的逻辑。逻辑讲述如下:
- 调用多路复用前函数(处理阻塞客户端、集群状态更新等)
- 多路复用,具体接口由抽象工厂实现
- 调用多路复用后函数(注册模块的处理)
- 检查是否有反转标记
- 根据反转标记进行先写后读(先执行写事件,再执行读事件)或者先读后写
定时事件
如图所示,这是Redis事件循环模块处理时间事件的逻辑。逻辑讲述如下:
- 遍历时间时间链表,取当前处理的事件
- 如果该事件已经被处理过,就从链表中清理出去
- 如果是本次处理触发之后才加入链表的事件,则跳过
- 增加引用计数防止误删,执行该事件
- 根据事件处理后的返回值,修改执行标记位(决定下次处理该事件是移除还是再次执行)
-
nodejs事件和事件循环详解
2021-01-14 16:40:41上篇文章我们简单的介绍了nodejs中的事件event和事件循环event loop。本文本文将会更进一步,继续讲解nodejs中的event,并探讨一下setTimeout,setImmediate和process.nextTick的区别。 -
浏览器事件循环
2020-05-14 08:07:36而这些任务不能是无序的,必须有个先来后到,浏览器内部需要一套预定的逻辑来有序处理这些任务,因此浏览器事件循环诞生了,再次强调,是浏览器事件循环,不是javascript事件循环,js只是浏览器事件循环的参与者。... -
JavaScript中事件循环和Nodejs中事件循环
2019-04-10 12:42:471.JavaScript中事件循环 可以参考《JavaScript忍者秘籍第二版》第十三章,讲解的很好。 JavaScript中事件循环,主要就在理解宏任务和微任务这两种异步任务。 宏任务(macrotask): setTimeOut 、 setInterval 、 ... -
Qt事件和事件循环
2017-11-14 11:48:14Qt事件和事件循环 在处理QT循环事件的时候遇到了问题,查了半天资料都没弄明白问题出在哪,后来找大牛同事问了一下,同事就给我写了QCoreApplication::processEvent()这个函数,好啦,终于搞定了,这里小记... -
python事件循环_如何实现基本事件循环?
2021-01-14 08:57:24Python:您可以查看Twisted reactor的实现,它可能是python中事件循环的最佳实现。Twisted中的reactor是接口的实现,您可以指定要运行的reactor类型:select、epoll、kqueue(都基于使用这些系统调用的c api),还有... -
深入理解JavaScript的事件循环(Event Loop) 一、什么是事件循环
2019-06-17 18:37:52深入理解JavaScript的事件循环(Event Loop) 一、什么是事件循环 JS的代码执行是基于一种事件循环的机制,之所以称作事件循环,MDN给出的解释为因为它经常被用于类似如下的方式来实现 while (queue.... -
Dart 事件循环
2019-12-27 16:24:30Dart 是事件驱动的体系结构,该结构基于具有单个事件循环和两个队列的单线程执行模型。 -
js事件循环
2018-05-19 17:20:51什么是事件循环,原来被人问到的时候就懵逼了,好像没有听过这个概念吗? 不应该是事件捕获,事件冒泡这种吗?事件循环是什么鬼? 什么是事件循环 单线程 一百度,原来真有事件循环这一概念,并且阮一峰大神的... -
浅谈js事件循环机制与Node的事件循环机制
2018-12-05 23:49:34js的事件循环机制比较简单 先执行主线程代码,执行完毕后,清空微任务队列,然后取出一个宏任务,然后清空微任务队列,如此循环 Node的事件循环比较复杂 Node的事件循环分为六个阶段 (1)timers计时器 执行... -
qt按钮功能循环触发_Qt事件和事件循环
2020-12-19 22:16:19在处理QT循环事件的时候遇到了...于是乎这里认真仔细的看了一下Qt的事件和事件循环。(引用了碎炎的博客)事件和事件循环作为一个事件驱动的工具包,事件和事件传递扮演者Qt架构中的中心角色。在本文中我们不会给出... -
Event Loop事件循环
2019-10-07 02:55:59Event Loop事件循环 asyncio.get_running_loop() 返回当前OS线程中的运行事件循环。 asyncio.get_event_loop() 获取当前事件循环。 asyncio.set_event_loop(loop) 将loop设置为当前OS线程的当前事件循环。 asyncio.... -
什么是事件循环
2019-09-07 01:26:41什么是事件循环 -
Nginx 事件循环
2016-10-12 08:05:02事件循环这个概念貌似在windows编程中提得更多,Linux程序却很少提及这个概念。本文所提及的事件循环其实就是worker cycle,由于此处将关注的不再是worker进程,而是worker进程在循环过程中关于事件处理的环节,因此... -
nodejs事件循环
2018-10-26 20:52:511. 只有一个主线程,node开始执行脚本时,会先进事件循环初始化(同步任务,发出异步请求,规划定时器生效时间,执行promise.nextTick等),这时事件循环还未开始。 ##### nodejs运行机制: V8引擎解析js脚本 解析... -
关于Qt的事件循环以及状态机事件循环的思考
2016-12-18 13:41:161.一般我们的事件循环都是由exec()来开启的,例如下面的例子: 1 QCoreApplicaton::exec() 2 QApplication::exec() 3 QDialog::exec() 4 QThread::exec() 5 QDrag::exec() 6 QMenu::exec() 这些都开启了事件... -
JS事件循环优先级
2019-02-18 21:41:20在JS里事件循环是很重要的概念,代码的执行栈都是以事件循环为标准的具体的事件循环概念这里就不详细解释描述,主要讲述事件循环中的执行优先级问题,这里涉及到到概念还有宏任务、微任务等 很多面试都遇到这段代码... -
探索node之事件循环
2020-10-24 21:12:02事件循环 Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。 Node.js 几乎每一个 API 都是支持回调函数的。 Node.js 基本上所有的事件... -
图解JavaScript事件循环
2020-08-13 16:24:12事件循环(Event Loop)是所有JavaScript开发者无论如何都要搞定的知识点之一,但是对于初学者来说,最初理解起来可能会有点困难。本文通过低分辨率的gif图像,以可视化的形式直观地讲解事件循环的机制。 首先我们来... -
Qt实现事件循环
2019-08-28 17:26:30//启动一个事件循环 QEventLoop::exit(); //结束事件循环 1)、子层循环具有父层循环的所有功能,调用exec()之后,Gui界面不会卡住,正常运行。 2)、调用exec()之后,不会执行后面的程序,调用exit()后才会跳出... -
js事件循环机制
2018-08-14 17:39:13从上一篇说明vue nextTick的文章中,多次出现“事件循环”这个名词,简单说明了事件循环的步骤,以便理解nextTick的运行时机,这篇文章将更为详细的分析下事件循环。在此之前需要了解JS单线程,及由此产生的同步... -
事件循环中的 event loop queue 和单个事件循环周期中的 job queue
2018-10-16 17:54:08js事件循环由一个 event loop queue 来管理,每当一个事件循环周期完成,会取 event loop queue 最前面的任务来执行,从而进入下一个事件循环周期。 setTimout、setInterval 方法告诉浏览器在一定时间后将任务函数... -
事件循环机制
2017-04-01 10:46:04我们知道JavaScript的一大特点就是单线程,而这个线程中拥有唯一的一个事件循环。JavaScript代码的执行过程中,除了依靠函数调用栈来搞定函数的执行顺序外,还依靠任务队列(task queue)来搞定另外一些代码的执行。...