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

前言

創(chuàng)始人:Ryan Dahl

Ryan Dahl

Ryan Dahl

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

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

Node.js簡介

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

1.1 簡介

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

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

1.2 特點

單線程

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

多線程、單線程的一個對比。

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

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

事件驅(qū)動event-driven

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

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

說是三個特點,實際上是一個特點,離開誰都不行,都玩兒不轉(zhuǎn)了。

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

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

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

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

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

Node.js安裝

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

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

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

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

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

Node.js沒有根目錄的概念,因為它根本沒有任何的web容器!

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

HTTP模塊

3.1 概述

Node.js中把一些獨立功能設(shè)計成為了模塊(module)。用require()內(nèi)置函數(shù)來進行引用。不需要任何的實際的文件,就可以調(diào)用內(nèi)置的模塊。
是因為有一些程序需要使用fs功能(文件讀取功能),有一些不用,所以為了效率,你用什么,就require什么。
●模塊的好處:
√ 減少重復代碼量,增加可讀性
√ 方便進行代碼規(guī)劃
√ 方便使用第三方模塊

3.2 server對象

可以用on語法監(jiān)聽某個事件,至于回調(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("這是首頁11");
5 }else{
6 res.setHeader("Content-Type","text/html;charset=UTF-8");
7 res.end("沒有這個頁面");
8 }
9 });

3.3 req對象

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

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

req.method “GET”、”POST”就是請求的類型

req.url 用戶請求的網(wǎ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對象

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

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

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

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

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

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

NPM

4.1 npm install命令

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

去社區(qū)搜索需求,然后點進去,看api。
如果要配置一個模塊,那么直接在cmd使用
1 npm install 模塊名字
安裝的時候,要注意,命令提示符的所在位置。
官網(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
任何一個包都必須有一個package.json文件,里面可以規(guī)定很多內(nèi)容。package.json就是這個包的身份證。
API:
https://docs.npmjs.com/getting-started/using-a-package.json

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

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

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

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

后臺模板,著名的有兩個,ejs和jade,是npm第三方包。

5.1 EJS
Embedded JavaScript templates
后臺模板引擎
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)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容