Node.js快速入門

一、概述

Node.js? is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.

Node.js是一個(gè)基于Google Chrome的V8引擎的JavaScript運(yùn)行環(huán)境的畴,它允許使用JavaScript語言編寫服務(wù)器端代碼。Node.js具有事件驅(qū)動(dòng)和I/O非阻塞兩大特點(diǎn),輕量而高效。

官網(wǎng)地址

二、安裝與運(yùn)行

從官網(wǎng)下載最新版本的Node.js蒙幻,直接安裝。安裝時(shí)選擇全部組件衣迷,并添加到環(huán)境變量Path中畏鼓。

運(yùn)行命令:node -v查看是否安裝成功。

運(yùn)行命令:node進(jìn)入到node.js的交互環(huán)境壶谒,可以輸入任意JavaScript語句云矫,并查看運(yùn)行結(jié)果。

運(yùn)行命令:node <*.js>直接執(zhí)行js文件里的內(nèi)容汗菜。

運(yùn)行命令:node --use_strict <*.js>為js文件開啟嚴(yán)格模式让禀。

安裝Node.js的時(shí)候,會(huì)自動(dòng)安裝包管理工具npm陨界。

運(yùn)行命令:npm -v查看npm的版本巡揍。

命令行模式會(huì)一次性執(zhí)行js文件,中間沒有交互菌瘪;交互模式則是每一行單獨(dú)執(zhí)行腮敌,可以進(jìn)行交互。

如果不想使用集成的IDE俏扩,可以使用VS Code編輯器進(jìn)行Node.js的開發(fā)和調(diào)試糜工。具體操作和配置可以參照VS Code的官網(wǎng)教程。

VS Code官網(wǎng)地址

Node.js Applications with VS Code

三动猬、模塊

在Node.js環(huán)境中啤斗,一個(gè)js文件就稱之為一個(gè)模塊。使用模塊提高了代碼的可維護(hù)性以及可重用性赁咙,還避免了函數(shù)名和變量名沖突钮莲。

當(dāng)在模塊中定義一個(gè)對象(對象、函數(shù)彼水、數(shù)組等)時(shí)崔拥,可以輸出這個(gè)對象以供其他模塊使用:

module.exports = object_name;

其他模塊要想使用這個(gè)對象,可以在模塊中引入該對象:

var variable_name = require('/path/to/the/module/module_name');

Tips:如果不指定路徑凤覆,Node會(huì)按照內(nèi)置模塊链瓦、全局模塊、當(dāng)前模塊的順序進(jìn)行查找盯桦。

1慈俯、基本模塊

在瀏覽器中,JavaScript有一個(gè)全局對象window拥峦;而在Node.js環(huán)境中贴膘,也有一個(gè)全局對象global。由于JavaScript代碼既能在瀏覽器執(zhí)行略号,也能在Node環(huán)境下執(zhí)行刑峡,可以通過全局對象名稱來判斷JavaScript代碼是在哪個(gè)環(huán)境下執(zhí)行的洋闽。

process也是Node.js提供的一個(gè)對象,表示當(dāng)前Node.js進(jìn)程突梦,進(jìn)程本身的事件由process來處理诫舅。

2、常用內(nèi)置模塊

fs模塊是文件系統(tǒng)模塊宫患,負(fù)責(zé)文件的讀寫操作刊懈,提供了同步和異步兩種方法。大部分作為服務(wù)端的代碼撮奏,必須使用異步代碼俏讹。但是在服務(wù)器啟動(dòng)時(shí)讀取配置文件,或結(jié)束時(shí)寫入狀態(tài)等操作畜吊,因?yàn)檫@些代碼只執(zhí)行一次,所以可以使用同步方法户矢。

讀文本文件:

var fs = require('fs');
fs.readFile('input.txt', 'utf-8', function (err, data) {
  if (err) {
    console.log(err);
  } else {
    console.log(data);
  }
});

其中玲献,readFile函數(shù)的第一個(gè)參數(shù)是文件名,第二個(gè)參數(shù)是文件編碼梯浪,第三個(gè)參數(shù)是一個(gè)回調(diào)函數(shù)捌年。回調(diào)函數(shù)的第一個(gè)參數(shù)代表錯(cuò)誤信息挂洛,第二個(gè)參數(shù)代表返回結(jié)果礼预。

讀二進(jìn)制文件:

var fs = require('fs');
fs.readFile('input.png', function (err, data) {
  if (err) {
    console.log(err);
  } else {
    console.log(data);
    console.log(data.length + ' bytes');
  }
});

其中,不需要文件編碼虏劲,并且回調(diào)函數(shù)的data參數(shù)將返回一個(gè)Buffer對象托酸。Buffer對象是一個(gè)包含零個(gè)或任意個(gè)字節(jié)的數(shù)組。

寫文件:

var fs = require('fs');
var data = 'Hello world';
fs.writeFile('output.txt', data, function (err) {
  if (err) {
    console.log(err);
  } else {
    console.log('success');
  }
});

其中柒巫,writeFile函數(shù)的第一個(gè)參數(shù)是文件名励堡,第二個(gè)參數(shù)是要寫入的數(shù)據(jù),第三個(gè)參數(shù)是回調(diào)函數(shù)堡掏。

讀取文件的相關(guān)信息:

fs.stat('input.txt', function (err, stat) {
  ...
});

stream是一個(gè)只能在服務(wù)端使用的模塊应结,用來支持流數(shù)據(jù)結(jié)構(gòu),流中的數(shù)據(jù)是有序的泉唁。流是一個(gè)對象鹅龄,使用時(shí)只需關(guān)注流的事件即可。data事件表示流的數(shù)據(jù)可以讀取亭畜,end事件表示流沒有數(shù)據(jù)可以讀取扮休,error事件表示出現(xiàn)錯(cuò)誤。

讀文件:

var fs = require('fs');
var rs = fs.createReadStream('input.txt', 'utf-8');
rs.on('data', function (chunk) {
  console.log('DATA:');
  console.log(chunk);
});
rs.on('end', function () {
  console.log('END');
});
rs.on('error', function (err) {
  console.log('ERROR: ' + err);
});

寫文件:

var fs = require('fs');
var ws1 = fs.createWriteStream('output1.txt', 'utf-8');
ws1.write('使用Stream寫入文本數(shù)據(jù)...\n');
ws1.write('END.');
ws1.end();

var ws2 = fs.createWriteStream('output2.txt');
ws2.write(new Buffer('使用Stream寫入二進(jìn)制數(shù)據(jù)...\n', 'utf-8'));
ws2.write(new Buffer('END.', 'utf-8'));
ws2.end();

可以使用管道操作pipe將讀取流和寫入流串聯(lián)起來:

var fs = require('fs');
var rs = fs.createReadStream('input.txt');
var ws = fs.createWriteStream('output.txt');
rs.pipe(ws);

默認(rèn)情況下贱案,當(dāng)讀取流的數(shù)據(jù)讀取完畢肛炮,會(huì)觸發(fā)end事件止吐,并自動(dòng)關(guān)閉寫入流。如果不想關(guān)閉侨糟,需要傳遞額外的參數(shù)碍扔。

readable.pipe(writable, { end: false });

http模塊是web應(yīng)用最常用的一個(gè)模塊,提供了request和response對象秕重。request對象封裝HTTP請求不同,調(diào)用request對象的屬性和方法,可以獲取HTTP請求的所有信息溶耘;response對象封裝HTTP響應(yīng)二拐,調(diào)用response對象的方法,可以把HTTP響應(yīng)返回給瀏覽器凳兵。

var http = require('http');
var server = http.createServer(function (request, response) {
  // 獲取HTTP請求的method和url
  console.log(request.method + ':' + request.url);
  // 將HTTP響應(yīng)的內(nèi)容寫入response
  response.writeHead(200, {'Content-Type': 'text/html'});
  response.end('<h1>Hello world!</h1>');
});
// 監(jiān)聽8080端口
server.listen(8080);

url模塊可以用來將URL字符串解析成一個(gè)Url對象百新,從而獲取想要的信息。

var url = require('url');
console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));

path模塊可以用來處理本地文件目錄庐扫。

var path = require('path');
// 解析當(dāng)前目錄
var workDir = path.resolve('.');
// 組合完整的文件路徑
var filePath = path.join(workDir, 'pub', 'index.html');

crypto模塊提供通用的加密和哈希算法饭望。

MD5哈希算法用來給任意數(shù)據(jù)一個(gè)簽名,通常用一個(gè)十六進(jìn)制字符串表示:

const crypto = require('crypto');
const hash = crypto.createHash('md5');
hash.update('Hello, world!');
console.log(hash.digest('hex'));

Hmac哈希算法可以利用MD5等算法形庭,另外還需要一個(gè)密鑰:

const crypto = require('crypto');
const hmac = crypto.createHmac('sha256', 'secret-key');
hmac.update('Hello, world!');
console.log(hmac.digest('hex'));

AES是一種常用的對稱加密算法铅辞,加密與解密使用同一個(gè)密鑰。crypto模塊提供了AES支持萨醒,但需要自行封裝斟珊。DiffieHellman算法是一種密鑰交換協(xié)議,可以讓雙方自行協(xié)商一個(gè)密鑰富纸。crypto模塊還可以處理數(shù)字證書囤踩。

四、Web開發(fā)

使用Node.js開發(fā)Web服務(wù)器端胜嗓,有幾點(diǎn)好處:

  • 前后端統(tǒng)一使用JavaScript高职,不需要切換語言
  • 異步處理大大提高了運(yùn)行速度

針對Node.js,出現(xiàn)了很多后端相關(guān)的Web框架辞州、ORM框架怔锌、模板引擎、測試框架变过、構(gòu)建工具等埃元。

1、Web框架Express/koa

Express是第一代最流行的Web服務(wù)端框架媚狰,它對Node.js的http進(jìn)行了封裝岛杀。雖然Express的API非常簡單,但是由于是基于ES5崭孤,要實(shí)現(xiàn)異步类嗤,只能使用回調(diào)糊肠。如果異步嵌套層次過多,代碼很難理解遗锣。

var express = require('express');
var app = express();
app.get('/', function (req, res) {
  res.send('Hello World!');
});
app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

koa1基于ES6货裹,使用generator實(shí)現(xiàn)異步。雖然使用generator在寫法上比回調(diào)簡單精偿,但其本意并不是用于異步弧圆。真正設(shè)計(jì)用來實(shí)現(xiàn)異步的是Promise,但Promise的寫法過于復(fù)雜笔咽。

var koa = require('koa');
var app = koa();
app.use('/test', function *() {
  yield doReadFile1();
  var data = yield doReadFile2();
  this.body = data;
});
app.listen(3000);

koa2基于ES7搔预,使用Promise和關(guān)鍵字async配合實(shí)現(xiàn)異步,同時(shí)兼容generator的寫法叶组。

app.use(async (ctx, next) => {
  await next();
  var data = await doReadFile();
  ctx.response.type = 'text/plain';
  ctx.response.body = data;
});

2拯田、ORM框架Sequelize

ORM技術(shù)是將關(guān)系型數(shù)據(jù)庫的表結(jié)構(gòu)映射到對象上,Sequelize返回Promise對象甩十,可以更好地進(jìn)行異步處理勿锅。

ES6:

Pet.findAll()
 .then(function (pets) {
   for (let pet in pets) {
     console.log(`${pet.id}: ${pet.name}`);
   }
 }).catch(function (err) {
   // error
 });

ES7:

(async () => {
  var pets = await Pet.findAll();
})();

要想使用Sequelize操作數(shù)據(jù)庫,首先需要?jiǎng)?chuàng)建一個(gè)Sequelize實(shí)例枣氧。然后定義數(shù)據(jù)模型Model,使用Sequelize映射數(shù)據(jù)庫表垮刹。這樣就可以調(diào)用實(shí)例的相應(yīng)方法來對數(shù)據(jù)庫進(jìn)行操作达吞。

Sequelize操作數(shù)據(jù)庫的一般步驟:

  • 通過Model對象的findAll()方法獲取實(shí)例
  • 如果要更新實(shí)例,先對實(shí)例屬性進(jìn)行賦值荒典,然后調(diào)用save()方法
  • 如果要?jiǎng)h除實(shí)例酪劫,直接調(diào)用destroy()方法

3、模板引擎Jade/Pug

Node.js默認(rèn)使用Jade作為模板引擎(現(xiàn)改名為Pug)寺董。Jade是Node.js的一個(gè)模塊覆糟,jade文件可以被預(yù)編譯為.js文件,也可以被編譯為目標(biāo)html代碼遮咖。

主頁

4滩字、測試框架Mocha

Mocha是JavaScript的單元測試框架,既可以在瀏覽器環(huán)境運(yùn)行御吞,也可以在Node.js的環(huán)境運(yùn)行麦箍。

特點(diǎn):

  • 既可以測試簡單的JavaScript函數(shù),又可以測試異步代碼
  • 既可以自動(dòng)運(yùn)行所有測試陶珠,也可以只運(yùn)行特定的測試
  • 可以支持before挟裂、after、beforeEach和afterEach來編寫初始化代碼

5揍诽、構(gòu)建工具Webpack

6诀蓉、WebSocket協(xié)議

WebSocket利用HTTP協(xié)議建立連接栗竖,在瀏覽器和服務(wù)器之間建立雙向通信的通道,服務(wù)器可以主動(dòng)向?yàn)g覽器發(fā)送消息渠啤,而不需要通過瀏覽器發(fā)送請求狐肢。

首先,WebSocket連接必須由瀏覽器發(fā)起埃篓,因?yàn)檎埱髤f(xié)議是一個(gè)標(biāo)準(zhǔn)的HTTP請求处坪。

GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13

與普通HTTP請求的區(qū)別:

  • GET請求的地址以ws://開頭
  • 請求頭Upgrade: websocketConnection: Upgrade表示連接將被轉(zhuǎn)換為WebSocket連接
  • Sec-WebSocket-Key用于標(biāo)識(shí)這個(gè)連接
  • Sec-WebSocket-Version指定WebSocket的協(xié)議版本

然后,如果服務(wù)器接受請求架专,會(huì)返回響應(yīng):

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string

其中同窘,響應(yīng)碼101表示將切換協(xié)議,切換后的協(xié)議通過Upgrade來指定部脚。

在Node.js中想邦,最常用的WebSocket模塊是ws。創(chuàng)建一個(gè)WebSocket的服務(wù)器實(shí)例:

const WebSocket = require('ws');
const WebSocketServer = WebSocket.Server;
const wss = new WebSocketServer({
  port: 3000
});

如果有WebSocket請求接入委刘,wss對象可以響應(yīng)connection事件來處理這個(gè)WebSocket丧没。對于每個(gè)WebSocket連接,都要對它綁定某些事件方法來處理不同的事件锡移。


參考文章:

廖雪峰:Node.js教程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呕童,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子淆珊,更是在濱河造成了極大的恐慌夺饲,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件施符,死亡現(xiàn)場離奇詭異往声,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)戳吝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門浩销,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人听哭,你說我怎么就攤上這事慢洋。” “怎么了欢唾?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵且警,是天一觀的道長。 經(jīng)常有香客問我礁遣,道長斑芜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任祟霍,我火速辦了婚禮杏头,結(jié)果婚禮上盈包,老公的妹妹穿的比我還像新娘。我一直安慰自己醇王,他們只是感情好呢燥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著寓娩,像睡著了一般叛氨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上棘伴,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天寞埠,我揣著相機(jī)與錄音,去河邊找鬼焊夸。 笑死仁连,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的阱穗。 我是一名探鬼主播饭冬,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼揪阶!你這毒婦竟也來了昌抠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對情侶失蹤鲁僚,失蹤者是張志新(化名)和其女友劉穎扰魂,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蕴茴,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年姐直,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倦淀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡声畏,死狀恐怖撞叽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情插龄,我是刑警寧澤愿棋,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站均牢,受9級(jí)特大地震影響糠雨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜徘跪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一甘邀、第九天 我趴在偏房一處隱蔽的房頂上張望琅攘。 院中可真熱鬧,春花似錦松邪、人聲如沸坞琴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剧辐。三九已至,卻和暖如春邮府,著一層夾襖步出監(jiān)牢的瞬間荧关,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工挟纱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留羞酗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓紊服,卻偏偏與公主長得像檀轨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子欺嗤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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

  • 1. 開始使用nodejs 1.1. Hello Word 好了参萄,讓我們開始實(shí)現(xiàn)第一個(gè) Node.js 程序吧。打...
    angelwgh閱讀 2,306評(píng)論 1 8
  • Node.js是目前非臣灞火熱的技術(shù)讹挎,但是它的誕生經(jīng)歷卻很奇特。 眾所周知吆玖,在Netscape設(shè)計(jì)出JavaScri...
    Myselfyan閱讀 4,071評(píng)論 2 58
  • Node.js是目前非惩怖#火熱的技術(shù),但是它的誕生經(jīng)歷卻很奇特沾乘。 眾所周知怜奖,在Netscape設(shè)計(jì)出JavaScri...
    w_zhuan閱讀 3,613評(píng)論 2 41
  • 古風(fēng)版的【愛請轉(zhuǎn)移】 若有幸他也聽聞 我依然在等
    397f2d7b7d0b閱讀 255評(píng)論 1 0
  • 大連北站開往丹東站歪玲,途徑莊河北站。 金州站掷匠,廣寧寺站滥崩,登沙河站,皮口站····· 我的天每一站都停讹语! 如果是個(gè)電影...
    郭永偉閱讀 199評(píng)論 0 0