Node.js入門和企業(yè)級(jí)應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn)

前言

創(chuàng)始人:Ryan Dahl

Ryan Dahl

Ryan Dahl

2004年,在紐約羅徹斯特大學(xué)數(shù)學(xué)系讀博士,研究一些分形、分類以及p-adic分析。
2006年,也許是厭倦了讀博的無(wú)聊,然后退學(xué),一個(gè)人去了智利的Valparaiso小鎮(zhèn)。
Ryan Dahl經(jīng)過(guò)兩年的工作后,成為了高性能Web服務(wù)器的專家,期間他開(kāi)始寫一些開(kāi)源項(xiàng)目幫助客戶解決Web服務(wù)器的高并發(fā)性能問(wèn)題,嘗試過(guò)的語(yǔ)言有Ruby、C、Lua,當(dāng)然這些嘗試都最終失敗了。

在他快絕望的時(shí)候,V8引擎來(lái)了。V8滿足他關(guān)于高性能Web服務(wù)器的想象:
● 沒(méi)有歷史包袱,沒(méi)有同步I/O。
● V8性能足夠好。
● JavaScript語(yǔ)言的閉包特性非常方便。
于是在2009年的2月,按新的想法他提交了項(xiàng)目的第一行代碼,這個(gè)項(xiàng)目的名字最終被定名為“node”。
2009年5月,Ryan Dahl正式向外界宣布他做的這個(gè)項(xiàng)目。
2009年底,Ryan Dahl在柏林舉行的JSConf EU會(huì)議上發(fā)表關(guān)于Node.js的演講,之后Node.js逐漸流行于世。

Node.js簡(jiǎn)介

Node.js是服務(wù)端開(kāi)發(fā)。之前學(xué)的jQuery、HTML5、CSS3都是前端開(kāi)發(fā),這些代碼都是在客戶端瀏覽器中執(zhí)行。
JavaScript傳統(tǒng)意義上是前臺(tái)語(yǔ)言,負(fù)責(zé)DOM組件、樣式、運(yùn)動(dòng)……。
Nodejs后端開(kāi)發(fā)關(guān)心GET、POST、表單的存儲(chǔ)等等。

1.1 簡(jiǎn)介

V8引擎本身就是用于Chrome瀏覽器的JS解釋部分,但是Ryan Dahl把V8搬到了服務(wù)器上,用于做服務(wù)器的軟件。
Node.js是一個(gè)讓JavaScript運(yùn)行在服務(wù)器端的開(kāi)發(fā)平臺(tái),它讓JavaScript的觸角伸到了服務(wù)器端,可以與PHP、JSP、Python、Ruby平起平坐。
但Node有點(diǎn)不同:
● Node.js不是一種獨(dú)立的語(yǔ)言,與PHP、ASP.Net、JSP、Python、Perl、Ruby的“既是語(yǔ)言,也是平臺(tái)”不同,Node.js的使用JavaScript進(jìn)行編程,運(yùn)行在Chrome V8引擎上。
● 與PHP、JSP等相比(PHP、ASP.Net、JSP、.net都需要運(yùn)行在服務(wù)器程序上),Node.js跳過(guò)了Apache、Nginx、IIS等HTTP服務(wù)器,它自己不用建設(shè)在任何服務(wù)器軟件之上。Node.js的許多設(shè)計(jì)理念與經(jīng)典架構(gòu)(LAMP = Linux + Apache + MySQL + PHP)有著很大的不同,可以提供強(qiáng)大的伸縮能力。

官網(wǎng):https://nodejs.org/en/
特點(diǎn):Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.

1.2 特點(diǎn)

單線程

在Java、PHP或者.net等服務(wù)器端語(yǔ)言中,會(huì)為每一個(gè)客戶端連接創(chuàng)建一個(gè)新的線程。而每個(gè)線程需要耗費(fèi)大約2MB內(nèi)存。
好處:操作系統(tǒng)完全不再有線程創(chuàng)建、銷毀的時(shí)間開(kāi)銷。
壞處:一個(gè)用戶造成了線程的崩潰,整個(gè)服務(wù)都崩潰了,其他人也崩潰了。

多線程、單線程的一個(gè)對(duì)比。

非阻塞I/O non-blocking I/O

例如,當(dāng)在訪問(wèn)數(shù)據(jù)庫(kù)取得數(shù)據(jù)的時(shí)候,需要一段時(shí)間。在傳統(tǒng)的單線程處理機(jī)制中,在執(zhí)行了訪問(wèn)數(shù)據(jù)庫(kù)代碼之后,整個(gè)線程都將暫停下來(lái),等待數(shù)據(jù)庫(kù)返回結(jié)果,才能執(zhí)行后面的代碼。也就是說(shuō),I/O阻塞了代碼的執(zhí)行,極大地降低了程序的執(zhí)行效率。

事件驅(qū)動(dòng)event-driven

在Node中,客戶端請(qǐng)求建立連接,提交數(shù)據(jù)等行為,會(huì)觸發(fā)相應(yīng)的事件。在Node中,在一個(gè)時(shí)刻,只能執(zhí)行一個(gè)事件回調(diào)函數(shù),但是在執(zhí)行一個(gè)事件回調(diào)函數(shù)的中途,可以轉(zhuǎn)而處理其他事件(比如,又有新用戶連接了),然后返回繼續(xù)執(zhí)行原事件的回調(diào)函數(shù),這種處理機(jī)制,稱為“事件環(huán)”機(jī)制。

單線程,單線程的好處,減少了內(nèi)存開(kāi)銷,操作系統(tǒng)的內(nèi)存換頁(yè)。
非阻塞I/O, 不會(huì)等I/O語(yǔ)句結(jié)束,而會(huì)執(zhí)行后面的語(yǔ)句。
事件機(jī)制,事件環(huán),不管是新用戶的請(qǐng)求,還是老用戶的I/O完成,都將以事件方式加入事件環(huán),等待調(diào)度。

說(shuō)是三個(gè)特點(diǎn),實(shí)際上是一個(gè)特點(diǎn),離開(kāi)誰(shuí)都不行,都玩兒不轉(zhuǎn)了。

1.3 適合開(kāi)發(fā)什么?

善于I/O,不善于計(jì)算。因?yàn)镹ode.js最擅長(zhǎng)的就是任務(wù)調(diào)度,如果你的業(yè)務(wù)有很多的CPU計(jì)算,實(shí)際上也相當(dāng)于這個(gè)計(jì)算阻塞了這個(gè)單線程,就不適合Node開(kāi)發(fā)。
當(dāng)應(yīng)用程序需要處理大量并發(fā)的I/O,而在向客戶端發(fā)出響應(yīng)之前,應(yīng)用程序內(nèi)部并不需要進(jìn)行非常復(fù)雜的處理的時(shí)候,Node.js非常適合。Node.js也非常適合與web socket配合,開(kāi)發(fā)長(zhǎng)連接的實(shí)時(shí)交互應(yīng)用程序。

比如:
● 用戶表單收集
● 考試系統(tǒng)
● 聊天室
● 圖文直播
● 提供JSON的API

1.4 Node.js無(wú)法挑戰(zhàn)老牌3P

Node.js本是就是極客追求性能極致的產(chǎn)物,缺少了很多服務(wù)器的健壯考量。所以Node不可能應(yīng)用在銀行、證券、電信等需要極高可靠性的業(yè)務(wù)中。

Node.js安裝

Node.js和Java非常像,跨平臺(tái)的。不管是Linux還是windows編程是完全一致的(有一些不一樣,比如路徑的表述)。Linux版本的Node.js環(huán)境和windows環(huán)境是不一樣的,但是編程語(yǔ)言一樣。很像Java虛擬機(jī)。

裝完之后,在系統(tǒng)的環(huán)境變量里面看一下:

環(huán)境變量,就已經(jīng)自動(dòng)的填寫進(jìn)去了,就是node安裝的目錄。

1 node 路徑名
推薦,不要使用完整的路徑名,而是通過(guò)先進(jìn)入案例文件夾,然后node相對(duì)地址
cd命令,表示更改當(dāng)前目錄。

Node.js是服務(wù)器的程序,寫的js語(yǔ)句,都將運(yùn)行在服務(wù)器上。返回給客戶的,都是已經(jīng)處理好的純html。

Node.js沒(méi)有根目錄的概念,因?yàn)樗緵](méi)有任何的web容器!

讓node.js提供一個(gè)靜態(tài)服務(wù),都非常難!

HTTP模塊

3.1 概述

Node.js中把一些獨(dú)立功能設(shè)計(jì)成為了模塊(module)。用require()內(nèi)置函數(shù)來(lái)進(jìn)行引用。不需要任何的實(shí)際的文件,就可以調(diào)用內(nèi)置的模塊。
是因?yàn)橛幸恍┏绦蛐枰褂胒s功能(文件讀取功能),有一些不用,所以為了效率,你用什么,就require什么。
●模塊的好處:
√ 減少重復(fù)代碼量,增加可讀性
√ 方便進(jìn)行代碼規(guī)劃
√ 方便使用第三方模塊

3.2 server對(duì)象

可以用on語(yǔ)法監(jiān)聽(tīng)某個(gè)事件,至于回調(diào)函數(shù)的形式,從API上看:
1 server.on("request",function(req, res){
2 if(req.url == "/"){
3 res.setHeader("Content-Type","text/html;charset=UTF-8");
4 res.end("這是首頁(yè)11");
5 }else{
6 res.setHeader("Content-Type","text/html;charset=UTF-8");
7 res.end("沒(méi)有這個(gè)頁(yè)面");
8 }
9 });

3.3 req對(duì)象

req就是每次上行請(qǐng)求的對(duì)象
req.header HTTP上行請(qǐng)求頭
1 console.log(req.headers);

req.httpVersion http請(qǐng)求的版本?,F(xiàn)在基本上都是1.1

req.method “GET”、”POST”就是請(qǐng)求的類型

req.url 用戶請(qǐng)求的網(wǎng)址
當(dāng)用戶的網(wǎng)址是:
http://127.0.0.1:3000/a/b/c/1.html?xingming=sefs&xfd=ere
req.url的值是:
/a/b/c/1.html?xingming=sefs&xfd=ere

3.4 res對(duì)象

res就是下行響應(yīng)對(duì)象

res.end() 每次都要有這個(gè)語(yǔ)句,表示這次的發(fā)送已經(jīng)結(jié)束,如果沒(méi)有,瀏覽器會(huì)一直轉(zhuǎn)。
參數(shù)必須是string、buffer(圖片、文件)。

res.write() 就是寫HTTP下行請(qǐng)求的body:
1 res.write("<h1>123</h1>");
2 res.write("<h1>456</h1>");
3 res.end("<h1>789</h1>");

res.setHeader() //設(shè)置返回的報(bào)文頭部

res.statusCode = 404; //設(shè)置狀態(tài)碼

res.writeHead() //和res.setHeader差不多

NPM

4.1 npm install命令

node.js package management node.js包管理器。
模塊就是一些功能的封裝,所以一些成熟的、經(jīng)常使用的功能,都有人封裝成為了模塊。并且放到了社區(qū)中,供人免費(fèi)下載。
這個(gè)偉大的社區(qū),叫做npm。 也是一個(gè)工具名字 node package management
https://www.npmjs.com/

去社區(qū)搜索需求,然后點(diǎn)進(jìn)去,看api。
如果要配置一個(gè)模塊,那么直接在cmd使用
1 npm install 模塊名字
安裝的時(shí)候,要注意,命令提示符的所在位置。
官網(wǎng) : https://www.npmjs.com/
如果被和諧了: https://npm.taobao.org/

npm命令已經(jīng)被集成在node.js中了,你安裝完node就有npm了。
在npmjs.org網(wǎng)站上搜索你需要的包,然后在cmd中:
npm install ****

我們就能夠用require去使用它。
1 var _ = require("underscore");

4.2 package.json
任何一個(gè)包都必須有一個(gè)package.json文件,里面可以規(guī)定很多內(nèi)容。package.json就是這個(gè)包的身份證。
API:
https://docs.npmjs.com/getting-started/using-a-package.json

npm也有文檔,這是package.json的介紹:
https://docs.npmjs.com/files/package.json
當(dāng)你把你的包發(fā)布到npm上的時(shí)候,下面的信息非常有用:
1 {
2 "name": "my_package", //項(xiàng)目名字
3 "version": "1.0.0", //版本號(hào)
4 "main": "index.js", //入口文件
5 "keywords": [], //關(guān)鍵詞,就是搜索什么npm上能夠顯示你
6 "author": "ag_dubs", //作者
7 "license": "ISC", //版權(quán)協(xié)議(許可證)
8 "repository": { //代碼托管倉(cāng)庫(kù),這個(gè)會(huì)自動(dòng)生成一個(gè)連接
9 "type": "git",
10 "url": "https://github.com/ashleygwilliams/my_package.git"
11 },
12 "bugs": { //如果發(fā)現(xiàn)bug應(yīng)該交給誰(shuí)
13 "url": "https://github.com/ashleygwilliams/my_package/issues"
14 },
1 "dependencies": {
2 "underscore": "*",
3 "date-format" : "0.0.2"
4 },
15 "homepage": "https://github.com/ashleygwilliams/my_package" //個(gè)人網(wǎng)站16 }

最最重要的信息,就是:
5 {
6 "dependencies": {
7 "underscore": "",
8 "date-format" : "
"
9 }10 }
這個(gè)叫做“依賴”。 k:v對(duì)兒是這個(gè)東西的版本號(hào)。
1.我們的依賴包,可能在隨時(shí)更新,我們永遠(yuǎn)想保持更新,或者某持某一個(gè)版本;
2.項(xiàng)目越來(lái)越大的時(shí)候,給別人看的時(shí)候,沒(méi)有必要再次共享我們引用的第三方模塊。

在cmd中,使用npm init可以初始化一個(gè)package.json文件,用回答問(wèn)題的方式生成新的package.json文件。
如果不想自己創(chuàng)建一個(gè)package.json文件,那么就要:npm init

五、模板引擎
1 <a href="<%= url %>"><img src="<%= imageURL %>" alt=""></a>
數(shù)據(jù)綁定,就成為一個(gè)完整的html字符串了。

后臺(tái)模板,著名的有兩個(gè),ejs和jade,是npm第三方包。

5.1 EJS
Embedded JavaScript templates
后臺(tái)模板引擎
1 <ul>
2 <% for(var i = 0 ; i < news.length ; i++){ %>
3 <li><%= news[i] %></li>
4 <% } %>
5 </ul>

1 var dictionary = {
2 a:6,
3 news : ["傳智新聞","高薪就業(yè)","nodejs好玩"]
4 };

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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