关于node.js:Nodejs核心入门

4次阅读

共计 6873 个字符,预计需要花费 18 分钟才能阅读完成。

前言:

因为以前学习 Node.js 并没有真正意义上的去学习它,而是粗略的学习了 npm 的常用命令和 Node.js 一些模块化的语法,因而昨天花了一天的工夫看了《Node.js 开发指南》一书。通过这本书倒是让我对 Node.js 的意识更为全面,但因为这本书出版工夫过早,有些 API 曾经产生了变动或曾经被废除,而对于学习 Node.js 来说,外围局部又是最为重要的一环,因而我配合官网文档对这本书的第四章 -Node.js 外围进行了总结与梳理,因为程度无限,如有疏漏与谬误,请斧正。

注释

外围模块是 Node.js 的心脏,次要是有一些精简高效的库组成(这方面和 Python 有很大的相似之处),为 Node.js 提供了根底的 API。次要内容包含:

Node.js 外围入门(一)

全局对象
常用工具
事件机制

Node.js 外围入门(二)

文件系统拜访
HTTP 服务器与客户端

全局对象

全局对象我想学过 JavaScript 的都晓得在浏览器是 window,在程序的任何中央都能够拜访到全局对象,而在 Node.js 中,这个全局对象换成了 global,所有的全局变量(除了 global 自身)都是 global 对象的属性。而咱们在 Node.js 中可能间接拜访的对象通常都是 global 的属性,如:console,process 等。

全局对象与全局变量

global 最基本的作用就是作为全局变量的宿主。依照 ECMAScript 标准,满足以下条件的变量即为全局变量:

  • 在最外层定义的变量(在 Node.js 中不存在,因为 Node.js 的代码在模块中执行,不存在在最外层定义变量)
  • 全局对象的属性
  • 隐式定义的变量(即未定义而间接进行赋值的变量)

当咱们定义一个全局变量的时候,这个全局变量会主动成为全局变量的属性。

process

process 对象是一个全局变量,它提供以后 Node.js 过程的相干信息,以及管制以后 Node.js 过程。通常咱们在写本地命令行程序的时候,少不了和它打交道。上面是它的最罕用的成员办法:

1.process.argv

process.argv 属性返回一个数组,这个数组蕴含了启动 Node.js 过程时的命令行参数。第一个元素为 process.execPath,第二个元素为以后执行的 JavaScript 文件门路,残余的元素为其余命令行参数。

例如存储一个名为 argv.js 的文件:

// print process.argv
process.argv.forEach((val, index) => {console.log(`${index}: ${val}`);
}); 

则命令行运行时这样的:

$ node process-args.js one two=three four

0: /usr/local/bin/node
1: /Users/mjr/work/node/process-args.js
2: one
3: two=three
4: four 

2.process.stdout

process.stdout 是规范输入流,通常咱们应用的 console.log()输入打印字符,而 process.stdout.write()函数提供了更为底层的接口。

process.stdout.write('请输出 num1 的值:');

3.process.stdin

process.stdin 是规范输出流,初始时它是暂停的,要想从规范输出读取数据,咱们必须复原流,并手动编写流的事件响应函数。

/*1: 申明变量 */
var num1, num2;
/*2:向屏幕输入,提示信息,要求输出 num1*/
process.stdout.write('请输出 num1 的值:');
/*3:监听用户的输出 */
process.stdin.on('data', function (chunk) {if (!num1) {num1 = Number(chunk);
       /*4:向屏幕输入,提示信息,要求输出 num2*/
       process.stdout.write('请输出 num2 的值');
   } else {num2 = Number(chunk);
       process.stdout.write('后果是:' + (num1 + num2));
   }
}); 

4.process.nextTick(callback[, …args])

…args <any> 调用 callback 时传递给它的额定参数
process.nextTick() 办法将 callback 增加到 ”next tick 队列 ”。一旦以后事件轮询队列的工作全副实现,在 next tick 队列中的所有 callbacks 会被顺次调用。
这种形式不是 setTimeout(fn, 0)的别名。它更加有效率,因而别用 setTimeout 去代替 process.nextTick。事件轮询随后的 ticks 调用,会在任何 I / O 事件(包含定时器)之前运行。

console.log('start');
process.nextTick(() => {console.log('nextTick callback');
});
console.log('scheduled');

// start
// scheduled
// nextTick callback 

4.console

console 模块提供了一个简略的调试控制台,相似于 Web 浏览器提供的 JavaScript 控制台。该模块导出了两个特定的组件:

  • 一个 Console 类,蕴含 console.log()、console.error() 和 console.warn() 等办法,能够被用于写入到任何 Node.js 流。
  • 一个全局的 console 实例,可被用于写入到 process.stdout 和 process.stderr。全局的 console 应用时无需调用 require(‘console’)。(留神:全局的 console 对象的办法既不总是同步的(如浏览器中相似的 API),也不总是异步的(如其余 Node.js 流)。

比方全局下的常见的 console 实例:

console.log('hello,world');
// hello,world
console.log('hello%s', 'world');
// helloworld
console.error(new Error('错误信息'));
//  Error: 错误信息
const name = '形容';
console.warn(` 正告 ${name}`);
// 正告形容
console.trace() // 向规范谬误流输入以后的调用栈 

常见的 Console 类:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello,world');
// hello,world
myConsole.log('hello%s', 'world');
// helloworld
myConsole.error(new Error('错误信息'));
// Error: 错误信息
const name = '形容';
myConsole.warn(` 正告 ${name}`);
// 正告形容 

常用工具 util

util 模块次要用于反对 Node.js 外部 API 的需要。大部分实用工具也可用于应用程序与模块开发者,用于补救外围 JavaScript 的性能的有余。它的能够这样调用:

const util = require('util');

1.util.inspect(object[, options])

util.inspect() 办法返回 object 的字符串示意,次要用于调试和谬误输入。附加的 options 可用于扭转格式化字符串的某些方面。它至多承受一个参数 objet,即要转换的参数,而 option 则是可选的,可选内容如下:

  • showHidden <boolean> 如果为 true,则 object 的不可枚举的符号与属性也会被包含在格式化后的后果中。默认为 false。
  • depth <number> 指定格式化 object 时递归的次数。这对查看大型简单对象很有用。默认为 2。若要有限地递归则传入 null。
  • colors <boolean> 如果为 true,则输入款式应用 ANSI 颜色代码。默认为 false,可自定义。
  • customInspect <boolean> 如果为 false,则 object 上自定义的 inspect(depth, opts) 函数不会被调用。默认为 true。
  • showProxy <boolean> 如果为 true,则 Proxy 对象的对象和函数会展现它们的 target 和 handler 对象。默认为 false。
  • maxArrayLength <number> 指定格式化时数组和 TypedArray 元素能蕴含的最大数量。默认为 100。设为 null 则显式全副数组元素。设为 0 或正数则不显式数组元素。
  • breakLength <number> 一个对象的键被拆分成多行的长度。设为 Infinity 则格式化一个对象为单行。默认为 60。

例如,查看 util 对象的所有属性:

const util = require('util');
console.log(util.inspect(util, { showHidden: true, depth: null})); 

2.util.callbackify(original)

util.callbackify(original)办法将 async 异步函数 (或者一个返回值为 Promise 的函数) 转换成遵循 Node.js 回调格调的函数。在回调函数中, 第一个参数 err 为 Promise rejected 的起因 (如果 Promise 状态为 resolved , err 为 null), 第二个参数则是 Promise 状态为 resolved 时的返回值。例如:

const util = require('util');

async function fn() {return await Promise.resolve('hello world');
}
const callbackFunction = util.callbackify(fn);

callbackFunction((err, ret) => {if (err) throw err;
 console.log(ret);
});
// hello world 

留神:

  • 回调函数是异步执行的, 并且有异样堆栈谬误追踪. 如果回调函数抛出一个异样, 过程会触发一个 ‘uncaughtException’ 异样, 如果没有被捕捉, 过程将会退出。
  • null 在回调函数中作为一个参数有其非凡的意义, 如果回调函数的首个参数为 Promise rejected 的起因且带有返回值, 且值能够转换成布尔值 false, 这个值会被封装在 Error 对象里, 能够通过属性 reason 获取。
function fn() {return Promise.reject(null);
}
const callbackFunction = util.callbackify(fn);

callbackFunction((err, ret) => {
   // 当 Promise 的 rejecte 是 null 时,它的 Error 与原始值都会被存储在 'reason' 中。err && err.hasOwnProperty('reason') && err.reason === null;  // true
}); 

事件驱动 events

events 是 Node.js 最重要的模块,起因是 Node.js 自身架构就是事件式的,大多数 Node.js 外围 API 都采纳习用的异步事件驱动架构,而它提供了惟一的接口,因而堪称 Node.js 事件编程的及时。events 模块不仅用于用户代码与 Node.js 上层事件循环的交互,还简直被所有的模块依赖。

所有能触发事件的对象都是 EventEmitter 类的实例。这些对象凋谢了一个 eventEmitter.on() 函数,容许将一个或多个函数绑定到会被对象触发的命名事件上。事件名称通常是驼峰式的字符串,但也能够应用任何无效的 JavaScript 属性名。对于每个事件,EventEmitter 反对若干个事件监听器。当事件发射时,注册到这个事件的事件监听器被顺次调用,事件参数作
为回调函数参数传递。

例如:

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
// eventEmitter.on() 办法用于注册监听器
myEmitter.on('event', () => {console.log('触发了一个事件!');
});
// eventEmitter.emit() 办法用于触发事件
myEmitter.emit('event'); 

上面让咱们来看看 EventEmitter 最罕用的 API:

-EventEmitter.on(event, listener) 办法能够增加 listener 函数到名为 eventName 的事件的监听器数组的开端。不会查看 listener 是否已被增加。屡次调用并传入雷同的 eventName 和 listener 会导致 listener 被增加与调用屡次。
-emitter.prependListener(eventName, listener)办法能够增加 listener 函数到名为 eventName 的事件的监听器数组的结尾。不会查看 listener 是否已被增加。屡次调用并传入雷同的 eventName 和 listener 会导致 listener 被增加与调用屡次。
-eventEmitter.emit() 办法容许将任意参数传给监听器函数。当一个一般的监听器函数被 EventEmitter 调用时,规范的 this 关键词会被设置指向监听器所附加的 EventEmitter。

// 实例:const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// 打印:
//   b
//   a 
  • EventEmitter.once(event, listener) 为指定事件注册一个单次监听器,即监听器最多只会触发一次,触发后立即解除该监听器。
server.once('connection', (stream) => {console.log('首次调用!');
}); 
  • EventEmitter.removeListener(event, listener) 移除指定事件的某个监听器,listener 必须是该事件曾经注册过的监听器。(留神:removeListener 最多只会从监听器数组里移除一个监听器实例。如果任何繁多的监听器被屡次增加到指定 eventName 的监听器数组中,则必须屡次调用 removeListener 能力移除每个实例。)
const callback = (stream) => {console.log('有连贯!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback); 
  • EventEmitter.removeAllListeners([event]) 移除所有事件的所有监听器,如果指定 event,则移除指定事件的所有监听器。
const callback = (stream) => {console.log('有连贯!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback); 

error 事件

EventEmitter 定义了一个非凡的事件 error,它蕴含了“谬误”的语义,咱们在遇到异样的时候通常会发射 error 事件。当 error 被发射时,EventEmitter 规定如果没有响
应的监听器,Node.js 会把它当作异样,退出程序并打印调用栈。咱们个别要为会发射 error 事件的对象设置监听器,防止遇到谬误后整个程序解体。

var events = require('events');
var emitter = new events.EventEmitter();
emitter.emit('error'); 

继承 EventEmitter

大多数状况下,咱们不会间接应用 EventEmitter,而是在对象中继承它,包含 fs,http 在内的只有是反对事件响应的外围模块都是 EventEmitter 的子类。这样做的起因有以下两个:

  • 具备某个实体性能的对象实现事件合乎语义,事件的监听和发射应该是一个对象的办法。
  • JavaScript 的对象机制是基于原型的,反对局部多重继承,继承 EventEmitter 不会打乱对象原有的继承关系。
正文完
 0