为了账号安全,请及时绑定邮箱和手机立即绑定

Node.js基础---event事件模块

全局对象
js中有个特殊的对象(全局对象global),他及其所有属性都可以在程序的任何地方访问,即全局变量,在浏览器js中,通常是window是全局对象,而Node.js中的全局对象是global,所有全局变量都是global对象的属性。
global最根本的作用是作为全局变量的宿主,全局变量:在最外层定义的变量,全局对象的属性,隐藏定义的变量。
在node.js中你不可能在最外层定义变量,因为所有用户代码都是属于当前模块的,而模块本身不是最外层上下文。

常用工具util

util是一个node.js核心模块,提供常用函数的集合,用于弥补核心Javascript的功能过于精简的不足;

util.inherits
util.inherits(constructor,superConstructor)是一个实现对象间原型继承的函数,js的面向对象特性是基于原型的,与常见的基于类的不同,JavaScript没有提供对象继承的语言特性,而是通过原型复制来实现的;

var  util = require("util");
function Base () {
        this.name = "base";
        this.base = 1995;

        this.sayHello = function() {
            console.log("hello "+ this.name );
         };
}
    Base.prototype.showName = function(){
            console.log(this.name);
 };

 function Sub () {
       this.name ="sub";
}
util.inherits(Sub, Base);

var objBase = new Base();

objBase.showName();
objBase.sayHello();
console.log(objBase);

var objSub = new Sub();
objSub.showName();
console.log(objSub);

定义了一个基础对象Base和一个继承自Base的Sub,Base有三个在构造函数内定义的属性和一个原型中定义的函数,通过util.inherits实现继承。
Sub仅仅继承了Base在原型中定义的函数,而构造函数内部的base属性和sayHello函数都没有被Sub继承;

util.inspect

util.inspect(object, [showHidden],[depth],[colors])
//是一个将任意对象转换为字符串的方法,通常用于调试和错误输出,他至少接受一个参数Object,即要转换的对象。

showHidden如果为true,将会输出更多隐藏信息;
depth表示最大递归的层数;
color为true输出格式会以ANSI颜色编码;
util.inspect并不会简单的将对象转换为字符串,即使该对象定义了toString方法也不会调用;

var util = require("util");
function Person () {
       this.name = "MGT360124";
        this.toString = function() {
           return this.name;
          }
}

var obj = new Person ();
console.log( util.inspect(obj) );
console.log( util.inpspect(obj,true) );

//Person { name: 'MGT360124', toString: [Function] }
//Person {
// name: 'MGT360124',
//toString:
//{ [Function]
//  [length]: 0,
//  [name]: '',
//  [arguments]: null,
//   [caller]: null,
//  [prototype]: { [constructor]: [Circular] } } }

处还有util.isArray(),util.isRegExp(),util.isDate(),util.isError()四个类型测试工具,util.format(),util.debug();

Node.js核心模块

事件驱动events是node.js最重要的模块,原因是node.js本身架构就是事件式的,而他提供了唯一的接口,所以堪称node.js事件编程的基石;

事件发射器
events模块只提供一个对象:events.EventEmitter。EventEmitter的核心就是事件发射与事件监听器功能封装。EventEmitter的每个事件由一个事件名和若干个参数组成;事件名是一个字符串,通常表达一定的语义,对于每个事件,EventEmitter支持若干个事件监听器,当事件发射时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。

//event.js
var events = require("events");
var emitter = new events();

emitter.on("someEvent",function(arg1,arg2){
      console.log("listener1",arg1,arg2);
});
emitter.on("someEvent",function(arg1,arg2){
      console.log("listener2",arg1,arg2);
});
emitter.emit("someEvent","byvoid",1994);
//运行结果
//listener1 byvoid 1994
//listener2 byvoid 1994

emitter为事件someEvent注册了两个了事件监听器,然后发射了someEvent事件,运行结果可以看到这两个事件监听器回调函数被先后调用;

EventEmitter常用的API
(1)EventEmitter.on(event,listener),为指定事件注册一个监听器,接受一个字符串event和一个回调函数listener。用于注册监听器;
(2)EventEmitter.emit(event, [arg1], [arg2], [...] )发射event事件,传递若干个可选参数到事件监听器的参数表;用于触发事件;
(3)EventEmitter.once(event, listener) 为指定事件注册一个单次监听器,即监听器最多只会触发一次,触发后立即解除该监听器;

const events = require("events');
const eventEmitter = new evnts();
let m =0;
eventEmitter.once("event",function(){
      console.log(++m);
})
eventEmitter.emit("event");
//输出1
eventEmitter.emit("event");
//忽略

(4)EventEmitter.removeListener(event, listener)移除指定事件的某个监听器,listener必须是该事件已经注册过的监听器;
(5)EventEmitter.removeAllListener([event])移除所有的事件监听器,如果指定event,则移除指定事件的所有监听器。
EventListener会按照 监听器注册的顺序同步地调用所有监听器。监听器函数可以使用setImmediate()或者process.nextTick()方法切换到异步操作模式:

const MyEmitter = require("events");
const myEmitter = new MyEmitter();
myEmitter.on("event",function(a,b){
      setImmediate( function(){
           console.log("这个是异步发生的");
      })
})
myEmitter.emit("event","a',"b");

error事件
当EventEmitter实例中发生错误时,会触发一个“error”事件。这在Node.js中是特殊情况。如果EventEmitter没有“error”事件注册至少一个监听器,则当“error”事件触发时,会抛出错误,打印堆跟踪,且退出node.js进程。

const MyEmitter = require("events");
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// 抛出错误,并使 Node.js 崩溃

为了防止Node.js进程崩溃,可以在process对象的uncaughtException事件上注册监听器;

const  events = require("events");
const myEmitter = new events();
process.on("uncaughtException",function(err){
          console.error("有错误");
});
myEmitter.emit("error",new Error("whoops!") );
//输出: 有错误

作为最佳实践,应该始终为“error”事件注册监听器

const events = require("events");
const myEmitter = new MyEmitter();
myEmitter.on("error",function(err) {
        console.log("有错误");
})
myEmitter.emit("error", new Error("whoops!") );
//输出:有错误
文件系统fs

fs模块是文件操作的封装,他提供了文件的读取,写入,更名,删除,遍历目录,链接等POSIX文件操作系统;与其他模块不同的是,fs提供了异步和同步的两个版本,如读取文件内容的函数有异步的fs.readFile()和同步的fs.readFileSync()。
fs.readFile( filename, [ encoding ] , [ callback(err,data) ] )是最简单的读取文件的函数,它接受一个必选参数filename,表示要读取的文件名,第二个参数encoding是可选的,表示文件的字符编码,callback是回调函数,用于接收文件的内容,如果指定encoding,data是一个解析后的字符串,否则data将会是以buffer形式表示的二进制数据;

var fs  =require("fs');
fs.readFile("./content.txt","utf-8",function(err,data){
  if(err){console.log(err)}
  else{ console.log(data)}
})
//运行结果是:
hello MGT360124 你好啊!

node.js 的异步编程接口习惯是以函数的最后一个参数为回调函数,通常是一个函数只有一个回调函数,回调函数是实际参数中第一个是err,其余的参数是其他返回的内容,如果没有发生错误,err的值回事null或者undefined,如果有错误,err通常是Error对象的实例;

fs.open(path, flags, [mode], [ callback(err,fd) ] )

是POSIXopen函数的封装,path为文件的路径,flags可以是:
(1)r:以读取模式打开文件。
(2)r+:以读写模式打开文件。
(3)w:以写入模式打开文件,如果文件不存在则创建。
(4)w+:以读写模式打开文件,如果文件不存在则创建。
(5)a:以追加模式打开文件,如果文件不存在则创建。
(6)a+:以读取追加模式打开文件,如果文件不存在则创建。
mode参数用于创建文件是给文件指定权限,默认是0666,回调函数将会传递一个文件描述fd(非负整数),表示操作系统内核为当前进程所维护的打开文件的记录表索引。

fs.readFile(fd,buffer,offset,length,position,[callback(err,bytesRead,buffer)] )

是POSIXread函数的封装,相比fs.readFile提供了更底层的接口。fs.read的功能是:
(1)从指定的文件描述符fd中读取数据并写入buffer指向的缓冲区对象,
(2)offset是buffer的写入偏移量,
(3)length是要从文件中读取的字节数,
(4)position是文件读取的起始位置,如果是position的值为null,则会从当前文件指针的位置读取,
(5)回调函数传递bytesRead和buffer,分别表示读取的字节数和缓冲区对象;

var fs = require("fs");
 fs.open('test.txt','utf-8',function(err,fd){
         if(err){
        console.log(err);
           return;
          }
       var buf = new Buffer(8);
       fs.read(fd,buf,0,8,null,function(err,btyeRead,buffer){
           if(err){
            console.err(err);
            return;
             }
           console.log("bytesRead: "+bytesRead);
           console.log(buffer);
      })
})
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消