写点什么

开源一夏 | 实战 Node.js 原理对于阻塞和 EventEmitter 及其继承的运用心得

作者:黎燃
  • 2022 年 8 月 16 日
    内蒙古
  • 本文字数:1973 字

    阅读完需:约 6 分钟

开源一夏 | 实战Node.js原理对于阻塞和EventEmitter及其继承的运用心得

基本概念


简单地说,Node.js 是在服务器端运行的 JavaScript。节点。


$ node
> console.log('Hello 黎燃!');Hello 黎燃!
复制代码


然而,对于 node JS,概念完全不同。


使用 node JS,我们不仅实现了一个应用程序,还实现了整个 HTTP 服务器。


事实上,我们的 web 应用程序和相应的 web 服务器基本相同。让我们了解一下 node JS 应用程序由以下部分组成:1.介绍所需模块:我们可以使用 require 命令加载 node JS 模块。2.创建服务器:服务器可以监听客户端的请求,类似于 Apache 和 nginx 等 HTTP 服务器。3.接收请求并响应请求的服务器很容易创建。客户端可以使用浏览器或终端发送 HTTP 请求,服务器收到请求后返回响应数据。

回调函数

Node.jsS 异步编程的直接体现是回调。

阻塞代码

异步编程依赖于回调,但不能说在使用回调后程序将是异步的。完成任务后将调用回调函数。节点使用大量回调函数。节点的所有 API 都支持回调函数。


读取文件后,我们返回文件内容作为回调函数的参数。这样,在执行代码时就不会阻塞或等待文件 I/O 操作。回调函数通常显示为函数的最后一个参数:


function foo1(name, age, callback) { }function foo2(value, callback1, callback2) { }
复制代码


创建主 JS 文件,代码如下:


var fs = require("fs");
var data = fs.readFileSync('input.txt');
console.log(data.toString());console.log("程序执行结束!");
复制代码

非阻塞代码

创建主 JS 文件,代码如下:


var fs = require("fs");
fs.readFile('input.txt', function (err, data) { if (err) return console.error(err); console.log(data.toString());});
console.log("程序执行结束!");
复制代码


在以上两个例子中,我们理解阻塞调用和非阻塞调用之间的区别。第一个实例在读取文件后执行程序。在第二个示例中,我们不需要等待文件被读取,因此我们可以在读取文件的同时执行以下代码,这大大提高了程序的性能。


因此,按顺序执行阻塞,不需要按顺序执行非阻塞。

Node.js 事件循环


Node.js 使用事件驱动模型。当 web 服务器接收到一个请求时,它会关闭并处理该请求,然后为下一个 web 请求提供服务。当请求完成时,它将被放回处理队列。当它到达队列的开头时,结果将返回给用户。引入 events 模块


var events = require('events');
复制代码


创建 eventEmitter 对象


var eventEmitter = new events.EventEmitter();
复制代码


绑定事件及事件的处理程序


eventEmitter.on('eventName', eventHandler);
复制代码


触发事件


eventEmitter.emit('eventName');
复制代码

Node 应用程序工作原理

创建主 JS 文件,代码如下:


var fs = require("fs");
fs.readFile('input.txt', function (err, data) { if (err){ console.log(err.stack); return; } console.log(data.toString());});console.log("程序执行完毕");
复制代码


在上述程序中,FS Readfile()是一个用于读取文件的异步函数。如果在读取文件期间发生错误,error err 对象将输出错误消息。


程序执行完毕


如果没有发生错误,readfile 将跳过 err 对象的输出,并通过回调函数输出文件内容。


接下来,我们删除输入 Txt 文件。执行结果如下:


程序执行完毕 Error: ENOENT, open 'input.txt'

EventEmitter 类

每次有新连接时,服务器对象的 net 将触发事件,而 readstream 对象的 FS 将在文件打开时触发事件。所有生成事件的对象都是 EventEmitter 实例中的事件。


引入 events 模块


var events = require('events');
复制代码


创建 eventEmitter 对象


var eventEmitter = new events.EventEmitter();
复制代码


如果在实例化 EventEmitter 对象期间发生错误,将触发错误事件。添加新侦听器时,将触发 newlistener 事件。删除侦听器时,将触发 RemovelListener 事件。


var EventEmitter = require('events').EventEmitter; var event = new EventEmitter(); event.on('some_event', function() {     console.log('some_event 事件触发'); }); setTimeout(function() {     event.emit('some_event'); }, 1000); 
复制代码


运行此代码,控制台在 1 秒_事件触发器后输出'some'。触发事件时,将依次调用注册到此事件的事件侦听器,并将事件参数作为回调函数参数传递。


var events = require('events'); var emitter = new events.EventEmitter(); emitter.on('someEvent', function(arg1, arg2) {     console.log('listener1', arg1, arg2); }); 
复制代码


on(event, listener)


注册指定事件的侦听器,并接受字符串事件和回调函数。


server.on('connection', function (stream) {  console.log('someone connected!');});
复制代码

继承 EventEmitter

大多数时候,我们不直接使用 EventEmitter,而是在对象中继承它。所有支持事件响应的核心模块,包括 FS、net 和 HTTP,都是 EventEmitter 的子类。


1.首先,具有实体函数的对象实现了符合语义的事件。事件的侦听和发生应该是对象的一种方法。


2.其次,JavaScript 的对象机制是基于原型的,支持部分多重继承。继承 EventEmitter 不会干扰对象的原始继承关系。

发布于: 刚刚阅读数: 3
用户头像

黎燃

关注

前端工程师 2022.05.06 加入

专注学习分享前端知识。

评论

发布
暂无评论
开源一夏 | 实战Node.js原理对于阻塞和EventEmitter及其继承的运用心得_开源_黎燃_InfoQ写作社区