node.js基礎(chǔ)回顧

Node.js 應(yīng)用是由哪幾部分組成的:

  • 引入 required 模塊:我們可以使用 require 指令來載入 Node.js 模塊。
  • 創(chuàng)建服務(wù)器:服務(wù)器可以監(jiān)聽客戶端的請求箭养,類似于 Apache 畅蹂、Nginx 等 HTTP 服務(wù)器像啼。
  • 接收請求與響應(yīng)請求: 服務(wù)器很容易創(chuàng)建谱邪,客戶端可以使用瀏覽器或終端發(fā)送 HTTP 請求邀杏,服務(wù)器接收請求后返回響應(yīng)數(shù)據(jù)领追。

創(chuàng)建簡單Node.js 應(yīng)用示例
步驟一:引入 required 模塊

var http = require("http");

步驟二:創(chuàng)建服務(wù)器

var http = require('http');
http.createServer(function (request, response) {
// 發(fā)送 HTTP 頭部 
// HTTP 狀態(tài)值: 200 : OK
// 內(nèi)容類型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 發(fā)送響應(yīng)數(shù)據(jù) "Hello World"
response.end('Hello World\n');
}).listen(8888);
// 終端打印如下信息
console.log('Server running at http://127.0.0.1:8888/'); 

步驟三:使用 node 命令執(zhí)行以上的代碼:

node server.js
Server running at http://127.0.0.1:8888/

步驟四:打開瀏覽器訪問 http://127.0.0.1:8888/他膳,你會看到一個寫著 "Hello World"的網(wǎng)頁。


分析Node.js 的 HTTP 服務(wù)器:

  • 第一行請求(require)Node.js 自帶的 http 模塊绒窑,并且把它賦值給 http 變量棕孙。
  • 接下來我們調(diào)用 http 模塊提供的函數(shù): createServer 。這個函數(shù)會返回 一個對象些膨,這個對象有一個叫做 listen 的方法蟀俊,這個方法有一個數(shù)值參數(shù), 指定這個 HTTP 服務(wù)器監(jiān)聽的端口號订雾。

Node.js REPL(交互式解釋器)
Node 自帶了交互式解釋器肢预,可以執(zhí)行以下任務(wù):

  • 讀取 - 讀取用戶輸入,解析輸入了Javascript 數(shù)據(jù)結(jié)構(gòu)并存儲在內(nèi)存中洼哎。
  • 執(zhí)行 - 執(zhí)行輸入的數(shù)據(jù)結(jié)構(gòu)
  • 打印 - 輸出結(jié)果
  • 循環(huán) - 循環(huán)操作以上步驟直到用戶兩次按下 ctrl-c 按鈕退出烫映。

Node 的交互式解釋器可以很好的調(diào)試 Javascript 代碼。

REPL 命令
ctrl + c - 退出當前終端噩峦。
ctrl + c 按下兩次 - 退出 Node REPL锭沟。
ctrl + d - 退出 Node REPL.
向上/向下 鍵 - 查看輸入的歷史命令

tab 鍵 - 列出當前命令


.help - 列出使用命令
.break - 退出多行表達式
.clear - 退出多行表達式
.save filename - 保存當前的 Node REPL 會話到指定文件
.load filename - 載入當前 Node REPL 會話的文件內(nèi)容。
按下兩次 ctrl + c 鍵就能退出 REPL

Node.js 回調(diào)函數(shù)

  • 阻塞代碼
    創(chuàng)建一個文件 input.txt 识补,內(nèi)容自定義族淮。
    創(chuàng)建 main.js 文件, 代碼如下:
var fs = require("fs");
var data = fs.readFileSync('input.txt');
console.log(data.toString());
console.log("程序執(zhí)行結(jié)束!");
  • 非阻塞代碼
    創(chuàng)建一個文件 input.txt ,內(nèi)容自定義。
    創(chuàng)建 main.js 文件, 代碼如下:
var fs = require("fs");
fs.readFile('input.txt', function (err, data) {
    if (err) return console.error(err);
    console.log(data.toString());
});
console.log("程序執(zhí)行結(jié)束!");

第一個實例(阻塞)在文件讀取完后才執(zhí)行完程序瞧筛。 第二個實例(非阻塞)不需要等待文件讀取完,這樣就可以在讀取文件時同時執(zhí)行接下來的代碼导盅,大大提高了程序的性能较幌。阻塞是按順序執(zhí)行的,而非阻塞是不需要按順序的白翻,所以如果需要處理回調(diào)函數(shù)的參數(shù)乍炉,我們就需要寫在回調(diào)函數(shù)內(nèi)。

Node.js 事件循環(huán)

  • Node.js 是單進程單線程應(yīng)用程序滤馍,但是因為 V8 引擎提供的異步執(zhí)行回調(diào)接口岛琼,通過這些接口可以處理大量的并發(fā),所以性能非常高巢株。
  • Node.js 幾乎每一個 API 都是支持回調(diào)函數(shù)的槐瑞。
  • Node.js 基本上所有的事件機制都是用設(shè)計模式中觀察者模式實現(xiàn)。
  • Node.js 單線程類似進入一個while(true)的事件循環(huán)阁苞,直到?jīng)]有事件觀察者退出困檩,每個異步事件都生成一個事件觀察者,如果有事件發(fā)生就調(diào)用該回調(diào)函數(shù).


Node.js EventEmitter
EventEmitter 類
events 模塊只提供了一個對象: events.EventEmitter那槽。EventEmitter 的核心就是事件觸發(fā)與事件監(jiān)聽器功能的封裝悼沿。可以通過require("events");來訪問該模塊骚灸。

// 引入 events 模塊
var events = require('events');
// 創(chuàng)建 eventEmitter 對象
var eventEmitter = new events.EventEmitter();

Node.js Buffer(緩沖區(qū))
JavaScript 語言自身只有字符串數(shù)據(jù)類型糟趾,沒有二進制數(shù)據(jù)類型。但在處理像TCP流或文件流時甚牲,必須使用到二進制數(shù)據(jù)义郑。因此在 Node.js中,定義了一個 Buffer 類鳖藕,該類用來創(chuàng)建一個專門存放二進制數(shù)據(jù)的緩存區(qū)魔慷。一個 Buffer 類似于一個整數(shù)數(shù)組,它對應(yīng)于 V8 堆內(nèi)存之外的一塊原始內(nèi)存著恩。

Node.js Stream(流)
Stream 是一個抽象接口院尔,Node 中有很多對象實現(xiàn)了這個接口。例如喉誊,對http 服務(wù)器發(fā)起請求的request 對象就是一個 Stream邀摆,還有stdout(標準輸出)。Node.js伍茄,Stream 有四種流類型:
Readable - 可讀操作栋盹。
Writable - 可寫操作。
Duplex - 可讀可寫操作.
Transform - 操作被寫入數(shù)據(jù)敷矫,然后讀出結(jié)果例获。
所有的 Stream 對象都是 EventEmitter 的實例汉额。常用的事件有:
data - 當有數(shù)據(jù)可讀時觸發(fā)。
end - 沒有更多的數(shù)據(jù)可讀時觸發(fā)榨汤。
error - 在接收和寫入過程中發(fā)生錯誤時觸發(fā)蠕搜。
finish - 所有數(shù)據(jù)已被寫入到底層系統(tǒng)時觸發(fā)。

Node.js模塊系統(tǒng)
一個 Node.js 文件就是一個模塊收壕,這個文件可能是JavaScript 代碼妓灌、JSON 或者編譯過的C/C++ 擴展。

//hello.js 模塊
function Hello() { 
    var name; 
    this.setName = function(thyName) { 
        name = thyName; 
    }; 
    this.sayHello = function() { 
        console.log('Hello ' + name); 
    }; 
}; 
module.exports = Hello;

//main.js 調(diào)用hello.js模塊(hello.js和node.js是在兩個不同的js文件中)
var Hello = require('./hello'); 
hello = new Hello(); 
hello.setName('BYVoid'); 
hello.sayHello(); 

Node.js 函數(shù)
在JavaScript中蜜宪,一個函數(shù)可以作為另一個函數(shù)的參數(shù)虫埂。我們可以先定義一個函數(shù),然后傳遞圃验,也可以在傳遞參數(shù)的地方直接定義函數(shù)掉伏。
Node.js中函數(shù)的使用與Javascript類似。

//把 say 函數(shù)作為execute函數(shù)的第一個變量進行了傳遞
function say(word) {
  console.log(word);
}
function execute(someFunction, value) {
  someFunction(value);
}
execute(say, "Hello");

匿名函數(shù)
我們可以把一個函數(shù)作為變量傳遞澳窑。但是我們不一定要繞這個"先定義岖免,再傳遞"的圈子,我們可以直接在另一個函數(shù)的括號中定義和傳遞這個函數(shù):

//execute 接受第一個參數(shù)的地方直接定義了我們準備傳遞給 execute 的函數(shù)照捡。用這種方式颅湘,我們甚至不用給這個函數(shù)起名字,這也是為什么它被叫做匿名函數(shù) 栗精。 
function execute(someFunction, value) {
  someFunction(value);
}
execute(function(word){ console.log(word) }, "Hello");

函數(shù)傳遞是如何讓HTTP服務(wù)器工作的

//我們向 createServer 函數(shù)傳遞了一個匿名函數(shù)闯参。 
var http = require("http");
http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}).listen(8888);

Node.js 全局對象
在瀏覽器 JavaScript 中,通常 window 是全局對象悲立, 而 Node.js 中的全局對象是 global

  • __filename 表示當前正在執(zhí)行的腳本的文件名鹿寨。它將輸出文件所在位置的絕對路徑,且和命令行參數(shù)所指定的文件名不一定相同薪夕。
  • __dirname 表示當前執(zhí)行腳本所在的目錄脚草。
  • setTimeout(cb, ms) 全局函數(shù)在指定的毫秒(ms)數(shù)后執(zhí)行指定函數(shù)(cb)。:setTimeout() 只執(zhí)行一次指定函數(shù)原献。返回一個代表定時器的句柄值馏慨。
    -clearTimeout( t ) 全局函數(shù)用于停止一個之前通過 setTimeout() 創(chuàng)建的定時器。 參數(shù) t 是通過 setTimeout() 函數(shù)創(chuàng)建的定時器姑隅。
  • setInterval(cb, ms) 全局函數(shù)在指定的毫秒(ms)數(shù)后執(zhí)行指定函數(shù)(cb)写隶。返回一個代表定時器的句柄值〗惭觯可以使用 clearInterval(t) 函數(shù)來清除定時器慕趴。setInterval() 方法會不停地調(diào)用函數(shù),直到 clearInterval() 被調(diào)用或窗口被關(guān)閉。
  • console 用于提供控制臺標準輸出
  • process 是一個全局變量冕房,即 global 對象的屬性躏啰。它用于描述當前Node.js 進程狀態(tài)的對象,提供了一個與操作系統(tǒng)的簡單接口耙册。

Node.js 常用工具

  • util.inherits(constructor, superConstructor)是一個實現(xiàn)對象間原型繼承 的函數(shù)丙唧。僅僅繼承了原型中定義的函數(shù),而構(gòu)造函數(shù)內(nèi)部創(chuàng)造的屬 性和 函數(shù)都沒有繼承觅玻。
  • util.inspect(object,[showHidden],[depth],[colors])是一個將任意對象轉(zhuǎn)換 為字符串的方法,通常用于調(diào)試和錯誤輸出培漏。
  • util.isArray(object)如果給定的參數(shù) "object" 是一個數(shù)組返回true溪厘,否則返回false。
  • util.isRegExp(object)如果給定的參數(shù) "object" 是一個正則表達式返回true牌柄,否則返回false畸悬。
  • util.isDate(object)如果給定的參數(shù) "object" 是一個日期返回true,否則返回false珊佣。
  • util.isError(object)如果給定的參數(shù) "object" 是一個錯誤對象返回true蹋宦,否則返回false。

Node.js 文件系統(tǒng)
異步的 fs.readFile() 和同步的 fs.readFileSync()咒锻。

  • 異步模式下打開文件:fs.open(path, flags[, mode], callback)
  • 異步模式下獲取文件信息:fs.stat(path, callback)
  • 異步模式下寫入文件:fs.writeFile(file, data[, options], callback)
  • 異步模式下讀取文件:fs.read(fd, buffer, offset, length, position, callback)
  • 異步模式下關(guān)閉文件:fs.close(fd, callback)
  • 異步模式下截取文件:fs.ftruncate(fd, len, callback)
  • 刪除文件:fs.unlink(path, callback)
  • 創(chuàng)建目錄:fs.mkdir(path[, mode], callback)
  • 讀取目錄:fs.readdir(path, callback)
  • 刪除目錄:fs.rmdir(path, callback)

使用 Node 創(chuàng)建 Web 服務(wù)器

var http = require('http');
var fs = require('fs');
var url = require('url');
// 創(chuàng)建服務(wù)器
http.createServer( function (request, response) {  
// 解析請求冷冗,包括文件名
   var pathname = url.parse(request.url).pathname;   
   // 輸出請求的文件名
   console.log("Request for " + pathname + " received.");   
   // 從文件系統(tǒng)中讀取請求的文件內(nèi)容
   fs.readFile(pathname.substr(1), function (err, data) {
      if (err) {
         console.log(err);
         // HTTP 狀態(tài)碼: 404 : NOT FOUND
         // Content Type: text/plain
         response.writeHead(404, {'Content-Type': 'text/html'});
      }else{             
         // HTTP 狀態(tài)碼: 200 : OK
         // Content Type: text/plain
         response.writeHead(200, {'Content-Type': 'text/html'});             
         // 響應(yīng)文件內(nèi)容
         response.write(data.toString());

index.html 文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
</head>
<body>
    <h1>我的第一個標題</h1>
    <p>我的第一個段落。</p>
</body>
</html>          
          }
          //  發(fā)送響應(yīng)數(shù)據(jù)
          response.end();
       });   
    }).listen(8080);
     // 控制臺會輸出以下信息
    console.log('Server running at http://127.0.0.1:8080/');

使用 Node 創(chuàng)建 Web 客戶端
Node 創(chuàng)建 Web 客戶端需要引入 http 模塊惑艇,創(chuàng)建 client.js 文件蒿辙,代碼如下所示:

var http = require('http'); 
// 用于請求的選項
var options = {
   host: 'localhost',
   port: '8080',
   path: '/index.html'  
}; 
// 處理響應(yīng)的回調(diào)函數(shù)
var callback = function(response){
   // 不斷更新數(shù)據(jù)
   var body = '';
   response.on('data', function(data) {
      body += data;
   });   
   response.on('end', function() {
      // 數(shù)據(jù)接收完成
      console.log(body);
   });
}
// 向服務(wù)端發(fā)送請求
var req = http.request(options, callback);
req.end();

新開一個終端,執(zhí)行 client.js 文件滨巴,輸出結(jié)果如下:

$ node  client.js     
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
</head>
<body>
    <h1>我的第一個標題</h1>
    <p>我的第一個段落思灌。</p>
</body>
</html>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市恭取,隨后出現(xiàn)的幾起案子泰偿,更是在濱河造成了極大的恐慌,老刑警劉巖蜈垮,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耗跛,死亡現(xiàn)場離奇詭異,居然都是意外死亡攒发,警方通過查閱死者的電腦和手機课兄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晨继,“玉大人烟阐,你說我怎么就攤上這事。” “怎么了蜒茄?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵唉擂,是天一觀的道長。 經(jīng)常有香客問我檀葛,道長玩祟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任屿聋,我火速辦了婚禮空扎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘润讥。我一直安慰自己转锈,他們只是感情好,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布楚殿。 她就那樣靜靜地躺著苇侵,像睡著了一般岸军。 火紅的嫁衣襯著肌膚如雪褪测。 梳的紋絲不亂的頭發(fā)上红竭,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音变隔,去河邊找鬼规伐。 笑死,一個胖子當著我的面吹牛匣缘,可吹牛的內(nèi)容都是我干的楷力。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼孵户,長吁一口氣:“原來是場噩夢啊……” “哼萧朝!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起夏哭,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤检柬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后竖配,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體何址,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年进胯,在試婚紗的時候發(fā)現(xiàn)自己被綠了用爪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡胁镐,死狀恐怖偎血,靈堂內(nèi)的尸體忽然破棺而出诸衔,到底是詐尸還是另有隱情,我是刑警寧澤颇玷,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布笨农,位于F島的核電站,受9級特大地震影響帖渠,放射性物質(zhì)發(fā)生泄漏谒亦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一空郊、第九天 我趴在偏房一處隱蔽的房頂上張望份招。 院中可真熱鬧,春花似錦狞甚、人聲如沸锁摔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嗤谚,卻和暖如春棺蛛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巩步。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工旁赊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人椅野。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓终畅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親竟闪。 傳聞我的和親對象是個殘疾皇子离福,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容