node.js中对Event Loop事件循环的理解与应用实例分析

来源:脚本之家  责任编辑:小易  

nodejs的几种模块加载方式 一.直接在exports对象中添加方法 1. 首先创建一个模块(module.js)module.js exports.One = function(){ console.log('first module'); }; 2.load.jsvar module =require('./module'); module.One(); 这样我们就可以在

本文实例讲述了node.js中对Event Loop事件循环的理解与应用。分享给大家供大家参考,具体如下:

Node.js EventEmitter Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。 Node.js里面的许多对象都会分发事件:一个net.Server对象会在每次有新连接时分发一个事件, 一个fs.readStream对象会在文件被打开的时候发出一个事件。

javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务。

Node.Js使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。这个模型非常高效可扩展性非常强,因为webserver一直接受请求

同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行。

在nodejs中有一个EventEmitter类,目的是实现各种事件的event处理。当需要指定绑定事件时,可以使用EventEmitter类的on方法或addListener方法.这两个方法实现原理相同,只是名称不一样.这两个方法都有两个参数,第一个参数为指定事件名 第二个参

异步任务是不进入主线程,而是进入一个 "任务队列" 里,"任务队列" 通知主线程,该异步任务才会进入主线程执行。

Node.js的应用程序都是单线程的。这就意味着即使计算机是多核或多处理器的,node.js的应用程序也只能利用其中一个,大大限制了系统性能。 随着堆栈变大,Node.js的垃圾收集器变得非常低效。随着堆栈使用空间超过1GB,垃圾收集的过程开始变得非常

任务的运行机制如下:

首先还是先放结论,在我看来,OPPOR11巴萨限量版,是一款对消费群定位精准的、具有相当的设计感的手机。OPPO这个品牌很有意思,尽管饱受争议,但是确实在实打实的开拓市场做手机。开拓市场方面大家都清楚,请了很多国内明星站台,做粉丝经济。这次又把目光放到了足球体育界,毕竟球迷在国内也是个巨大的群体,更何况巴萨在国内的知名度。我勉强也算半个球迷吧,这样的手机对我而言还是挺讨喜的。所以说R11巴萨版这款手机在消费群上面定位精准,就是因为这一点,算是品牌的差异化经营吧,无论是哪个社群,都有相应的手机可供选择。但这一点还不是R11最打动我的地方,最打动我的还是它的设计。首先咱们是普通消费者,不是很懂设计

1、所有同步任务在主线程上执行,形成一个 "执行栈",注意栈是先进后出的。

社会发展方向是正规化,阳光化,更注重安全,其次才是观赏性,说到底是强化了人权,现在没有人是为了生存去打拳,曾经的菜市场,码头等一些商业聚集地从历史上就被黑社会控制,现在不是都偃旗息鼓了吗,世界的走向还是以文明进步为主题。

2、主线程外,有一个 "任务队列" ,只要异步任务处理完有结果了,就在 "任务队列" 中放置一个事件,注意队列是先进先出的。

这种现象要分年龄来看待。首先,孩子处在婴幼儿阶段,他们的行为只是对新事物的一种好奇。孩子来到这个世界后,对他来说一切都是陌生的。他对周围的事物都会充满新鲜感,想亲自去触摸和感受。这个阶段的孩子是没有物的所属权的概念的。而且他们也很容易受到其他事物的诱惑,那么当遇到这种情况,我们首先要告诉孩子这是别人的东西,不是我们自己的。然后可以用其他有趣的事物去引开他的注意或者带他离开现场,去别的地方。其次,孩子已经能分清物的所属权了,但仍然喜欢要别人的东西。对这种情况,作为家长我们就要反思自己,是不是自己平时的教育方法不对?是不是不管什么东西我们都会去满足孩子?从来没有拒绝过孩子?如果答案是从未拒绝过,那

3、一旦 "执行栈" 中所有同步任务执行完毕。系统读取 "任务队列" 中的事件,对应的异步任务。放入 "执行栈" 中,开始执行。

有钱真的很重要,像想买个包,想配条裙,想做个护肤护理,昨晚还相中了一双鞋,你说那样不要钱,没钱的帅哥一大堆,有钱的帅哥围着追。那都是有钱和没钱的基本区别。你说这世界钱不重要,那就没美女与靓女之间的区别。美不美,选一个呗!

4、主线程不断重复第三步,这种循环从 "任务队列" 中读取事件处理的这种运行机制称为Event Loop(事件循环)。

"执行栈" 中的同步代码总是比 "任务队列"中的异步任务之前运行。

function fun() { setTimeout(function () { console.log('异步任务'); }, 0); console.log(1); console.log(2); console.log(3); console.log(4); console.log(5); } fun();

上面的代码,console.log代码写在setTimeout后面,但仍然先执行。

"任务队列" 是一个队列,队列的特性是先进先出。看下面代码:

function fun() { console.log(1); setTimeout(function () { console.log(2); setTimeout(function () { console.log(3); }, 0); }, 0); console.log(4); } fun();

输出结果为 1  4  2  3,打印 2 的setTimeout任务比打印 3 的setTimeout任务先进入队列,所以会先运行。

对于异步操作,像ajax,只有操作成功后返回结果,才会进入 "任务队列" 中,而不是调用的时候就放入队列中。看下面代码:

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> function ajax() { var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://mail.163.com/', true); xhr.send(); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responseText); } }; } function fun() { console.log(1); ajax(); setTimeout(function () { console.log(2); }, 1000); console.log(3); } fun(); </script> </body> </html>

ajax() 与 setTimeout 谁先进入队列,谁先输出,是需要看两者消耗时间,谁更短。时间短的会先进入队列先运行。

setTimeout 与 setInterval 运行机制一样,都是在指定时间把事件插入到 "任务队列" 尾部。区别是前者只执行一次,后者可反复执行。

node.js 还为我们提供了,process.nextTick 和 setImmediate 与 "任务队列" 有关的方法。

process.nextTick 会把回调函数放在当前 "执行栈" 的尾部。也就是说是在读取 "任务队列" 之前运行。

function fun() { console.log(1); setTimeout(function () { console.log(2); }, 0); process.nextTick(function () { console.log(3); process.nextTick(function () { console.log(4); }); }); process.nextTick(function () { console.log(5); }); console.log(6); } fun();

上面的代码会输出 1  6  3  5  4  2 ,注意process.nextTick会把回调函数放在 "执行栈" 的尾部。

同步代码最先输出 1  6,然后 3 的先放入尾部,然后 5 的跟在 3 后面。3先执行,然后把 4 放入到 5 的后面。5执行完后,再执行4,最后读取 "任务队列" 中的输出2。

setImmediate 会把回调函数放在当前 "任务队列" 的尾部。也就是下一次事件循环Event Loop时执行。

function fun() { console.log(1); setTimeout(function () { console.log(2); }, 0); setImmediate(function () { console.log(3); }); console.log(4); } fun();

上面的代码是会输出 1  4  2  3 还是 1  4  3  2 是不确定的,因为setTimeout 与 setImmediate 都会在下一次事件循环Event Loop中触发,所以输出是不确定的。

希望本文所述对大家node.js程序设计有所帮助。

扩展阅读,根据您访问的内容系统为您准备了以下内容,希望对您有帮助。

nodejs中,什么是事件循环

Node JS是单线程应用程序,但它通过事件和回调概念,支持并发。 由于Node

JS每一个API是异步的,作为一个单独的线程,它使用异步函数调用,以保持并发性。Node

JS使用观察者模式。Node线程保持一个事件循环,每当任何任务得到完成,它触发这标志着该事件侦听器函数执行相应的事件。

事件驱动编程

Node.js大量使用事件,这也是为何Node.js是相当快相对于其他类似的技术。当Node启动其服务器,它可以简单地启动它的变量,声明的函数,然后简单地等待发生的事件。

在事件驱动的应用中,通常主循环监听事件,然后触发回调函数时被检测到这些事件之一。

尽管事件似乎类似于回调。不同之处在于如下事实,当异步函数返回其结果的回调函数被调用的地方作为对观察者模式的事件处理。

监听事件的功能作为观察员。每当一个事件被触发,它的监听函数就开始执行。Node.js具有多个内置通过事件模块和用于将事件绑定和事件侦听,如下

EventEmitter类可用事件:

// Import events module

var events = require('events');

// Create an eventEmitter object

var eventEmitter = new events.EventEmitter();

以下为事件处理程序绑定使用事件的语法:

// Bind event and even handler as follows

eventEmitter.on('eventName', eventHandler);

我们可以通过编程触发一个事件,如下所示:

// Fire an event

eventEmitter.emit('eventName');

例子

创建一个名为具有以下代码main.js一个js文件:

// Import events module

var events = require('events');

// Create an eventEmitter object

var eventEmitter = new events.EventEmitter();

// Create an event handler as follows

var connectHandler = function connected() {

console.log('connection succesful.');

// Fire the data_received event

eventEmitter.emit('data_received');

}

// Bind the connection event with the handler

eventEmitter.on('connection', connectHandler);

// Bind the data_received event with the anonymous function

eventEmitter.on('data_received', function(){

console.log('data received succesfully.');

});

// Fire the connection event

eventEmitter.emit('connection');

console.log("Program Ended.");

现在让我们试着运行上面的程序作为检查的输出:

$ mnode main.js

这将产生以下结果:

connection succesful.

data received succesfully.

Program Ended.

mac终端运行nodejs总是提示events.js:183错误(内详)到达怎么解决?

1337端口被占用了

查出占用的进程,杀掉后重新执行试下追问但是我设置的端口是80,为什么会到1337?追答可能其中的某个组件监听的,这个错本身是端口占用造成本回答被提问者和网友采纳

Node.js 与 Python 优劣势分别有哪些?

声明:没有一种绝对好的语言。

Node.js > Python 的地方

快:这个快有两方面,第一是V8引擎快,在V8引擎背后操刀的是Lars Bak大神,他创造过高性能SmallTalk引擎和Java Hotspot引擎(现在Java的默认VM),他带领下的V8引擎让Javascript速度达到了一个新的阶段。第二是异步执行,Node.js功能上是一个基于V8引擎的异步网络和IO Library,和Python的Twisted很像,不同的是Node.js的event loop是很底层的深入在语言中的,可以想象成整个文件在执行的时候就在一个很大的event loop里。

npm:npm可以说是用起来最顺手的package management了,npm作为Node.js的官方package management,汇集了整个社区最集中的资源。不像Python经历过easy_install和pip,还有2to3的问题。

Windows支持:Node.js有微软的加持,Windows基本被视为一等公民来支持,libuv已经可以很好的做到统一跨平台的API;而Python虽然也对Windows有官方的支持,但是总感觉是二等公民,时不时出些问题。

Python > Node.js 的地方

语言:就单纯从语言的角度来说,Python写起来要比Javascript舒服很多。Javascript设计本身有许多缺陷,毕竟当时设计的时候只是作为在浏览器中做一些简单任务的script,所以代码一旦庞大,维护还是有困难(不过Node.js的module很大的改善了这个问题)。不过用Coffeescript可以很大的改善Javascript,几乎可以和Python等同。

成熟:成熟包括语言本身已经成熟,还有Framework和ecosystem也很庞大。Node.js的绝大多数framework都很新,有的API一直在变,有的感觉已经不在维护,总之没有一个像Django那种百足之虫感觉的framework。Python的主流ORM SQLalchemy也很成熟。

Python 和 Node.js 很难分高下的地方

异步Style:Node.js的异步Style是CPS,也就是层层callback,基于event,和浏览器中的Javascript很像。CPS好处是让熟悉浏览器Javascript的人能很快上手,学习难度也不大。缺点是逻辑一复杂,就变得很难维护,基本上需要通过async.js这种library,或者用promise。Python的异步除了和Node.js很像的Twisted之外,也有基于coroutine的gevent,coroutine让异步代码维护起来更容易,不过学习曲线陡。

应用场景:如果是一个CRUD的app,那么想都不想直接是Python,Node.js本身不擅长CRUD的app(绝大多数Node.js都是直接裸在外面的,而不是有一个Nginx在前面,否则websocket就不能用了,不过新版nginx开始支持websocket),代码又不好维护,而Python的WSGI很适合,成熟的stack也有很多。如果更偏向于real-time,比如一个chat room,那么Node.js实现更容易。这两个应用场景还是有差别的。

Node.js里面大量使用定时器会有问题吗

首先,Jut团队所研发的产品称为操作数据中心(operations data hub)。该产品是一个专门为研发团队所设计的流分析平台,主要用于收集日志以及事件等操作数据,然后根据整体做分析和关联。其核心功能就是要能够同时处理实时数据、历史数据、结构和非结构数据。具体产品架构如下图所示。

从上图可以看出,该产品的核心就是数据引擎,包括底层大数据后端和JPC(Juttle Processing Core)两部分。其中,整体系统需要依赖ElasticSearch和Cassandra等这些大数据后端分系统,进行历史数据的处理和存储以及一般数据的复原和管理;JPC采用了Node.js,完成同等对待历史数据和实时数据、利用日志数据/度量数据/事件数据提出问题以及发送实时数据到浏览器来利用d3进行可视化等。而且,JPC负责运行Juttle程序。当用户点击Juttle程序时,浏览器把程序发送到JPC,将其转换为JavaScript进行执行。Galbraith提出,Jut团队选择JPC中使用Node.js的原因包括采用JavaScript等高级编程语言可以快速完成建模和迭代过程;鉴于程序前端采用JavaScript实现,后端同样采用JavaScript可以方便前后端配合和沟通;Node.js拥有强大的开源社区,使得开发团队可以有效利用社区的力量等三个方面。JPC就利用了社区中103个NPM包,同时也共享了自己开发的7个包。

尽管Node.js拥有着非常好的特性,JPC的开发团队还是遇到了一些Node.js不能直接解决的问题:

Node.js的应用程序都是单线程的。这就意味着即使计算机是多核或多处理器的,node.js的应用程序也只能利用其中一个,大大*了系统性能。

随着堆栈变大,Node.js的垃圾收集器变得非常低效。随着堆栈使用空间超过1GB,垃圾收集的过程开始变得非常慢,会严重影响程序的性能。

因为以上的问题,Node.js*了堆栈所能使用的空间为1.5GB。一旦超过该范围,系统就会出错。

为了保证Jut系统的高效性,Jut团队想出了一些解决方案。

首先,针对Node.js单线程引起的性能低下问题,Jut团队采用了尽量避免利用Node.js进行计算的方式。JPC会把Juttle流图切割为一些子图,然后在Jut平台的更深层再进行高效执行。以ElasticSearch为例,在未优化之前,数据请求的流程为:ElasticSearch把相关数据从磁盘中取出->编码为JSON->通过HTTP协议发送给JPC->JPC解码JSON文件,执行预想的计算。然而,ElasticSearch拥有一种聚合(Aggregation)功能,能够跨数据集执行计算。这样,一次大的请求就可以优化为一个ElasticSearch聚合,避免了中间多次JSON转换以及Node.js针对大规模数据进行计算的过程。而且,ElasticSearch和Cassandra都是采用Java编写,可以有效利用多核或多处理器资源,实现高效率并行计算。总之,通过尽量避免在Node.js中进行计算的方式,Jut团队有效提高了系统的性能。

其次,关于堆栈空间问题。每当用户让Node.js服务器向其他服务器发送请求时,用户都会提供一些相应的函数,来对未来返回的数据进行处理。Node.js就会把这些函数放到event loop中,等待数据返回,然后调用相应的函数进行处理。这种类似中断的处理方式,可以大大提高单线程Node.js的效率。然而,一旦event loop中其中一个函数计算的时间过长,系统就会出现问题。以用户向Node.js发送从其他服务器中请求若干行的数据,然后对这些数据进行数学计算为例。如果请求的数据超过了1.5GB堆栈大小的*,计算过程就会占用Node.js很长一段时间,甚至无法完成。由于Node.js为单线程,在这段时间内,新的请求或者新返回的数据只能放置在event loop的待办列表中。这样,Node.js服务器的反应时间将会大大增加,影响其他请求的正常处理。

Node.js真的有高并发优势吗

有的,Nodejs的无阻塞模型对应高并发的是很不错的

首先nodejs的模型是基于event loop的,个人理解比较类似的就是java的circular buffer

假设现在又10W的并发,如果是传统的http服务器,可能是我这儿就锁住当前的HTTP请求,直到buffer全部写完再返回结果,这样就会有大量的等待产生

nodejs的处理方式是,我把你的请求相应的IO全部放入event loop池中,谁的buffer写完了就返回就行了,所有的事件都是有一个handle统一轮询这一轮里面谁写完了谁返回,所以即使并发再大,也是无阻塞的

nginx的原理类似,不过nginx是基于哈希分配的,通过哈希码去创建当前的请求任务,并开辟设置好的内存块随时更新状态

  • 本文相关:
  • node.js事件循环(event loop)和线程池详解
  • node.js event loop各阶段讲解
  • node.js中事件轮询(event loop)的解析
  • 深入理解node.js 事件循环和回调函数
  • 小结node.js中非阻塞io和事件循环
  • 深入浅析node.js 事件循环
  • 实例分析js与node.js中的事件循环
  • 详解nodejs异步i/o和事件循环
  • node.js 事件循环详解及实例
  • 浅谈node 异步io和事件循环
  • nodejs监控事件循环异常示例详解
  • node.js中的events.emitter.listeners方法使用说明
  • 深入理解nodejs搭建静态服务器(实现命令行)
  • node koa2实现上传图片并且同步上传到七牛云存储
  • node.js中cluster的使用教程
  • node 解析图片二维码的内容代码实例
  • node.js 8 中的 util.promisify的详解
  • 搭建基于express框架运行环境的方法步骤
  • nodejs进程管理模块forever详解
  • node.js开发之访问redis数据库教程
  • nodejs实现获取本地文件夹下图片信息功能示例
  • nodejs中,什么是事件循环
  • mac终端运行nodejs总是提示events.js:183错误(内...
  • Node.js 与 Python 优劣势分别有哪些?
  • Node.js里面大量使用定时器会有问题吗
  • Node.js真的有高并发优势吗
  • 如何导入nodejs工程
  • node.js eventemitter.on 不手动remove 会被回收吗
  • 如何理解nodejs中的事件驱动
  • node.js eventemitter.on 不手动remove 会被回收吗
  • 如何更好的利用Node.js的性能极限
  • 免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved