由於之前學習Node.js並無真正意義上的去學習它,而是粗略的學習了npm的經常使用命令和Node.js一些模塊化的語法,所以昨天花了一天的時間看了《Node.js開發指南》一書。經過這本書卻是讓我對Node.js的認識更爲全面,但因爲這本書出版時間過早,有些API已經發生了變化或已經被廢棄,而對於學習Node.js來講,核心部分又是最爲重要的一環,所以我配合官方文檔對這本書的第四章-Node.js核心進行了總結與梳理,因爲水平有限,若有疏漏與錯誤,請指正。node
核心模塊是Node.js的心臟,主要是有一些精簡高效的庫組成(這方面和Python有很大的類似之處),爲Node.js提供了基礎的API。主要內容包括:npm
Node.js核心入門(一)編程
Node.js核心入門(二)數組
全局對象我想學過JavaScript的都知道在瀏覽器是window,在程序的任何地方均可以訪問到全局對象,而在Node.js中,這個全局對象換成了global,全部的全局變量(除了global自己)都是global對象的屬性。而咱們在Node.js中可以直接訪問的對象一般都是global的屬性,如:console,process等。瀏覽器
global最根本的做用就是做爲全局變量的宿主。按照ECMAScript規範,知足如下條件的變量即爲全局變量:bash
當咱們定義一個全局變量的時候,這個全局變量會自動成爲全局變量的屬性。服務器
process 對象是一個全局變量,它提供當前 Node.js 進程的相關信息,以及控制當前 Node.js 進程。一般咱們在寫本地命令行程序的時候,少不了和它打交道。下面是它的最經常使用的成員方法:架構
process.argv 屬性返回一個數組,這個數組包含了啓動Node.js進程時的命令行參數。第一個元素爲process.execPath,第二個元素爲當前執行的JavaScript文件路徑,剩餘的元素爲其餘命令行參數。異步
例如存儲一個名爲argv.js的文件:async
// 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
複製代碼
process.stdout是標準輸出流,一般咱們使用的console.log()輸出打印字符,而process.stdout.write()函數提供了更爲底層的接口。
process.stdout.write('請輸入num1的值:');
複製代碼
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));
}
});
複製代碼
...args 調用 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
複製代碼
console 模塊提供了一個簡單的調試控制檯,相似於 Web 瀏覽器提供的 JavaScript 控制檯。該模塊導出了兩個特定的組件:
好比全局下的常見的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 模塊主要用於支持 Node.js 內部 API 的需求。 大部分實用工具也可用於應用程序與模塊開發者,用於彌補核心JavaScript的功能的不足。它的能夠這樣調用:
const util = require('util');
複製代碼
util.inspect() 方法返回 object 的字符串表示,主要用於調試和錯誤輸出。 附加的 options 可用於改變格式化字符串的某些方面。它至少接受一個參數objet,即要轉換的參數,而option則是可選的,可選內容以下:
例如,查看 util 對象的全部屬性:
const util = require('util');
console.log(util.inspect(util, { showHidden: true, depth: null }));
複製代碼
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
複製代碼
注意:
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是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:
// 實例:
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// 打印:
// b
// a
複製代碼
server.once('connection', (stream) => {
console.log('首次調用!');
});
複製代碼
const callback = (stream) => {
console.log('有鏈接!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
複製代碼
const callback = (stream) => {
console.log('有鏈接!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
複製代碼
EventEmitter 定義了一個特殊的事件 error ,它包含了「錯誤」的語義,咱們在遇到異常的時候一般會發射 error 事件。當 error被髮射時,EventEmitter規定若是沒有響 應的監聽器,Node.js 會把它看成異常,退出程序並打印調用棧。咱們通常要爲會發射 error 事件的對象設置監聽器,避免遇到錯誤後整個程序崩潰。
var events = require('events');
var emitter = new events.EventEmitter();
emitter.emit('error');
複製代碼
大多數狀況下,咱們不會直接使用EventEmitter,而是在對象中繼承它,包括fs,http在內的只要是支持事件響應的核心模塊都是EventEmitter的子類。這樣作的緣由有如下兩個: