一、知識結構:
http模塊:配置簡單 的web服務,npm/cnpm工具
express框架:express中間件進行服務配置;路由;請求處理;
DB服務:學習使用mysql關系型數據庫;
web接口服務:使用express、koa簡單配置接口服務、JSON解析;
nodejs RESTful API:提供跨語言、跨平台的服務接口、支持web/app
node文件系統:服務端基本的文件讀寫操作
二、Node.js簡介:
Node.js是一個讓JavaScript運行在服務器端的開發平台,它讓JavaScript的觸角伸到了服務器端。但Node.js似乎與其它服務器端語言有點不同:
Node.js不是一種獨立的語言,與PHP、Python等“既是語言,又是平台”不同,Node.js使用的是JavaScript進行編程,Node.js是一個工具,語言仍是JavaScript。
與PHP、JSP等相比,Node.js跳過了apache、tomcat、nginx、iis等http服務器,它自己不用建立在任何服務器軟件之上。
Node.js哲學:花最小的硬件成本,追求更高的並發,更高的處理性能。
Node采用一系列“非阻塞”庫來支持事件循環的方式。本質上就是為文件系統、數據庫之類的資源提供接口。向文件系統發送一個請求時,無需等待硬盤(尋址並檢索文件),硬盤准備好的時候非阻塞接口會通知Node。該模型以可擴展的方式簡化了對慢資源的訪問, 直觀,易懂。尤其是對於熟悉onmouseover、onclick等DOM事件的用戶,更有一種似曾相識的感覺。
Node.js特點:
單線程:
說明Node.js是單線程的一個實例 :
Node.js的優點:
Node.js可以在不新增額外線程的情況下,依然可以對任務進行並發處理 —— Node.js是單線程的。它通過事件循環(event loop)來實現並發操作,對此,我們應該要充分利用這一點 —— 盡可能的避免阻塞操作,取而代之,多使用非阻塞操作。
事件驅動:
異步回調:相當於一個服務員照顧多個顧客
說明實例:當有多個用戶同時訪問的時候,會出現同一個用戶進來和讀取完畢不連續的情況
只要I/O越多,Node.js宏觀上越並行;但運算越多,Node.js宏觀上越不並行,此時網頁打開速度嚴重變慢,因為計算過程中CPU只能為某一用戶服務,難以脫身,所以Node.js線程就被這一用戶霸占了。
因此Node.js適合開發I/O多的業務,而不適合計算任務繁重的業務。
非阻塞I/O:
例如:當訪問數據庫取得數據的時候,需要一段較長的時間,在傳統的處理機制中,在執行了訪問數據庫代碼之后,整個線程都將暫停下來等待數據庫返回結果才能執行后面的代碼,也就是說I/O阻塞了后面代碼的執行,極大的降低了程序的執行效率。
由於Node.js采用了非阻塞I/O機制,因此在執行了訪問數據庫的代碼之后,將立即轉而執行其后面的代碼,將數據庫返回結果的處理代碼放在回調函數中,從而提高了程序的執行效率。
當某個I/O執行完畢時,將以事件的形式通知執行I/O操作的線程,線程執行這個事件的回調函數。為了處理異步I/O,線程必須有事件循環,不斷的檢查有沒有未處理的事件,依次予以處理。
在阻塞模式下,一個線程只能處理一項任務,要想提高吞吐量必須通過多線程。而非阻塞模式下,一個線程永遠在執行計算操作,這個線程的核心利用率永遠是100%,所以這個是一個特別有哲理的解決方案:與其人多,但好多人閑着,還不如一個人玩命,往死里干活。
Node..js適合開發的業務:
當業務程序需要處理大量並發的I/O,而在向客戶端發出響應之前,應用程序內部並不需要進行非常復雜的處理的時候,Node..js非常合適。Node..js也非常適合和websocket配合,開發長連接的實時交互應用程序,比如:用戶表單收集、考試系統、聊天室、圖文直播、提供JSON的API(為MVVM框架使用)。
三、命令行窗口(cmd窗口/終端):
1、常用的命令:
dir:列出當前文件夾下的所有文件;
cd 目錄名:進入到指定的目錄;
md 目錄名:創建一個指定的文件夾;
rd 目錄名:刪除一個指定的文件夾;
2、目錄:
.:表示當前目錄;
..:表示上一級目錄;
3、環境變量:
path:當我們在命令行窗口打開一個文件或調用一個程序時系統會首先在當前目錄下尋找程序,如果找到了則直接打開,如果沒有找到則會依次到環境變量path的路徑中尋找,直到找到為止,如果沒有找到則會報錯。
4、快速進入指定文件夾的方法:
在指定文件夾的地址欄中輸入:cmd
四、進程和線程:
進程:負責為程序的運行提供必備的環境,相當於工廠中的車間;
線程:計算機中最小的計算單元,負責執行進程中的程序,相當於工廠中的工人。
五、node執行js文件:
cmd中進入hello.js所在文件夾,cmd中輸入:
六、node整合WebStorm:
WebStorm菜單的File->Settings:搜索node,找到Node.js and NPM,在右側的Node interpreter中輸入node.exe所在位置即可。
七、WebStorm中node代碼提示:
WebStorm菜單的File->Settings:搜索node,找到Node.js and NPM,在右側的Coding Assistance中啟用即可。
八、模塊化:
在Node中,一個js文件就是一個模塊;
在 Node中,每一個js文件的js代碼都是獨立運行在一個函數中,比如:
其實是:
而不是全局作用域,所以一個模塊中的變量和函數在其它模塊中無法訪問 。
在Node中,通過require()函數來引入外部模塊,require()中可以傳遞一個文件的路徑作為參數,node將會自動根據該路徑來引入外部模塊,這里路徑如果使用相對路徑,則必須以“.”或者“..”開頭;
我們可以通過exports來向外部暴露變量或者方法,只需要將需要暴露給外部的變量或者方法設置為exprots的屬性即可。
使用require()引入模塊以后,該函數會返回一個對象,這個對象代表的是引入的模塊。
我們使用require()引入外部模塊時,使用的就是模塊標識。
模塊分成兩大類:
核心模塊:由node引擎提供的模塊,核心模塊的標識就是模塊的名字;
文件模塊:用戶自定義的模塊,文件模塊的標識就是文件的路徑。
node模塊中用var定義的變量都是局部變量,取消掉var時定義的變量才是全部變量:
輸出:
由此可知:
當node在執行模塊中的代碼時,它首先會在代碼的最頂部添加如下代碼:
在代碼的最底部,添加如下代碼:
實際上,模塊中的代碼都是包裝在一個函數中執行的,並且在函數執行時,同時傳遞了5個實參:
exports:該對象用來將對象或者函數暴露到外部,
require:函數,用來引入外部的模塊,
module:用來代表的是當前模塊本身,exports就是模塊的屬性。既可以用exports導出,也可以用module.exports導出兩者指向的是同一個對象,
__filename:當前模塊的完整路徑,
__dirname:當前模塊所在文件夾的完整路徑
九、exports與modules.exports的區別:
本質上兩者是相等的,但是exports只能通過“.”的方式向外暴露內部變量,而modules.exports既可以通過“.”的形式,也可以直接賦值;
十、包簡介:
CommonJS的包規范允許我們將相關的模塊組合在一起,形成一組完整的工具。
CommonJS的包規范包括包結構和包描述文件。
包結構:
package.json:必須
bin:可執行的二進制文件,非必須
lib:js文件,非必須;
doc:文檔,非必須;
test:單元測試,非必須
包描述文件:
用於表達非代碼相關的信息,它是一個json文件-package.json,位於包的根目錄下,是包的重要組成部分。
十一、npm(Node package manager)簡介:
相當於360安全衛士里的軟件管家。
對於node而言,npm幫助其完成了第三方模塊的發布、安裝和依賴等。借助npm,node與第三方模塊之間形成了很好的一個生態系統。
npm -v:查看npm版本;
npm version: 查看所有模塊的版本;
npm search 包名:搜索包;
npm install/i 包名 :安裝包;
npm remove/r 包名:刪除包;
npm remove/r 包名 --save:將包名在依賴中刪除(node _modules中不刪除);
npm install 包名 --save:安裝包並添加到依賴中(package.json的dependencies中);
npm install:下載當前項目所依賴的包(package.json的dependencies中的包);
npm install 包名 -g:全局安裝包(全局安裝的包一般是一些工具)
十二、node模塊引用:
通過npm下載的包都放到node_modules中,我們通過npm下載的包直接通過包名引用即可。
node在通過模塊名字來引用模塊時它會首先在當前目錄的node_modules中尋找是否含有該模塊,如果有則直接使用,如果沒有則直接去上一級目錄的node_modules中尋找,如果有則直接使用,如果沒有,則繼續再去上一級目錄中尋找,直到找到磁盤的根目錄,如果依然沒有,則直接報錯。
十三、EventEmitter:
Node.js 所有的異步 I/O 操作在完成時都會發送一個事件到事件隊列。
Node.js 里面的許多對象都會分發事件:一個 net.Server 對象會在每次有新連接時觸發一個事件, 一個 fs.readStream 對象會在文件被打開的時候觸發一個事件。 所有這些產生事件的對象都是 events.EventEmitter 的實例。
events 模塊只提供了一個對象: events.EventEmitter。EventEmitter 的核心就是事件觸發與事件監聽器功能的封裝。
你可以通過require("events");來訪問該模塊。
EventEmitter 對象如果在實例化時發生錯誤,會觸發 error 事件。當添加新的監聽器時,newListener 事件會觸發,當監聽器被移除時,removeListener 事件被觸發。
下面我們用一個簡單的例子說明 EventEmitter 的用法:
執行結果如下:
運行這段代碼,1 秒后控制台輸出了 'some_event 事件觸發'。其原理是 event 對象注冊了事件 some_event 的一個監聽器,然后我們通過 setTimeout 在 1000 毫秒以后向 event 對象發送事件 some_event,此時會調用some_event 的監聽器。
EventEmitter 的每個事件由一個事件名和若干個參數組成,事件名是一個字符串,通常表達一定的語義。對於每個事件,EventEmitter 支持 若干個事件監聽器。
當事件觸發時,注冊到這個事件的事件監聽器被依次調用,事件參數作為回調函數參數傳遞。
讓我們以下面的例子解釋這個過程:
執行以上代碼,運行的結果如下:
以上例子中,emitter 為事件 someEvent 注冊了兩個事件監聽器,然后觸發了 someEvent 事件。
運行結果中可以看到兩個事件監聽器回調函數被先后調用。 這就是EventEmitter最簡單的用法。
EventEmitter 提供了多個屬性,如 on 和 emit。on 函數用於綁定事件函數,emit 屬性用於觸發一個事件。接下來我們來具體看下 EventEmitter 的屬性介紹。
方法
| 序號 | 方法 & 描述 |
|---|---|
| 1 | addListener(event, listener) 為指定事件添加一個監聽器到監聽器數組的尾部。 |
| 2 | on(event, listener) 為指定事件注冊一個監聽器,接受一個字符串 event 和一個回調函數。 |
| 3 | once(event, listener) 為指定事件注冊一個單次監聽器,即 監聽器最多只會觸發一次,觸發后立刻解除該監聽器。 |
| 4 | removeListener(event, listener) 移除指定事件的某個監聽器,監聽器必須是該事件已經注冊過的監聽器。 它接受兩個參數,第一個是事件名稱,第二個是回調函數名稱。 |
| 5 | removeAllListeners([event]) 移除所有事件的所有監聽器, 如果指定事件,則移除指定事件的所有監聽器。 |
| 6 | setMaxListeners(n) 默認情況下, EventEmitters 如果你添加的監聽器超過 10 個就會輸出警告信息。 setMaxListeners 函數用於提高監聽器的默認限制的數量。 |
| 7 | listeners(event) 返回指定事件的監聽器數組。 |
| 8 | emit(event, [arg1], [arg2], [...]) 按參數的順序執行每個監聽器,如果事件有注冊監聽返回 true,否則返回 false。 |
類方法
| 序號 | 方法 & 描述 |
|---|---|
| 1 | listenerCount(emitter, event) 返回指定事件的監聽器數量。 |
events.EventEmitter.listenerCount(emitter, eventName) //已廢棄,不推薦
events.emitter.listenerCount(eventName) //推薦
事件
| 序號 | 事件 & 描述 |
|---|---|
| 1 | newListener
該事件在添加新監聽器時被觸發。 |
| 2 | removeListener
從指定監聽器數組中刪除一個監聽器。需要注意的是,此操作將會改變處於被刪監聽器之后的那些監聽器的索引。 |
實例
以下實例通過 connection(連接)事件演示了 EventEmitter 類的應用。
創建 main.js 文件,代碼如下:
以上代碼,執行結果如下所示:
十四、使用 GET 或 POST 請求發送數據:
server.js
handler.js
index.html
十五、常用工具:
十六、Buffer緩存區:
Buffer的結構和數組很像,操作的方法也和數組類似;
數組中不能存儲二進制的文件,而Buffer就是專門用來存儲二進制數據;
為什么要用Buffer?Node.js其實就做兩件事,一是接收請求,另一個是發送請求,請求都是以二進制的方式傳遞的,接收以后或者發送之前二進制數據都是放在緩存中。
使用Buffer不需要引用模塊,直接使用即可;
在Buffer中存儲的是二進制數據,但在顯示時是以十六進制的形式顯示;存入時的數字可以是任何進制,但在控制台或者頁面就是一定只能以十進制輸出顯示,如果存儲的是字符的話可以用其它進制顯示,方式str.toString(x);
Buffer中每一個元素的范圍是00-ff(16進制) <=> 0-255(10進制) <=> 00000000-11111111(2進制);
計算機中1個0或者1個1我們稱之為1位(bit),計算機中數據是以字節為單位傳輸的;
8bit=1byte(1字節);
1024byte=1kb;
1024kb=1mb;
1024mb=1gb;
1024gb=1tb;
Buffer中的1個元素占用內存的1個字節;
Buffer的大小一旦確定,則不能修改,Buffer實際上是對底層內存的直接操作;
十七、路由:
server.js
review.html
404.html
重構路由代碼:
app.js
server.js
router.js
handler.js
十八、文件系統(fs):
文件系統簡單來說就是通過Node.js來操作系統中的文件;
使用文件系統首先需要引入fs模塊,fs是核心模塊,直接引入不需要下載;
文件的寫入步驟:
手動步驟:
a、打開文件;
b、向文件中寫入內容;
c、保存並關閉文件;
1、同步寫入文件:
2、異步寫入文件:
3、簡單文件寫入(不需要打開文件):
| Flag | 描述 |
|---|---|
| r | 以讀取模式打開文件。如果文件不存在拋出異常。 |
| r+ | 以讀寫模式打開文件。如果文件不存在拋出異常。 |
| rs | 以同步的方式讀取文件。 |
| rs+ | 以同步的方式讀取和寫入文件。 |
| w | 以寫入模式打開文件,如果文件不存在則創建。 |
| wx | 類似 'w',但是如果文件路徑存在,則文件寫入失敗。 |
| w+ | 以讀寫模式打開文件,如果文件不存在則創建。 |
| wx+ | 類似 'w+', 但是如果文件路徑存在,則文件讀寫失敗。 |
| a | 以追加模式打開文件,如果文件不存在則創建。 |
| ax | 類似 'a', 但是如果文件路徑存在,則文件追加失敗。 |
| a+ | 以讀取追加模式打開文件,如果文件不存在則創建。 |
| ax+ | 類似 'a+', 但是如果文件路徑存在,則文件讀取追加失敗。 |
4、使用絕對路徑寫入文件:
5、流式文件寫入:
同步、異步、簡單文件的寫入都不太適合大文件的寫入,性能較差,容易導致內存溢出。
5、簡單文件讀取:
6、流式文件讀取:
7、fs其它操作:
• 驗證路徑是否存在
– fs.existsSync(path)
• 獲取文件信息
– fs.stat(path, callback)
– fs.statSync(path)
• 刪除文件
– fs.unlink(path, callback)
– fs.unlinkSync(path)
列出文件
– fs.readdir(path[, options], callback)
– fs.readdirSync(path[, options])
• 截斷文件
– fs.truncate(path, len, callback)
– fs.truncateSync(path, len)
• 建立目錄
– fs.mkdir(path[, mode], callback)
– fs.mkdirSync(path[, mode])
刪除目錄
– fs.rmdir(path, callback)
– fs.rmdirSync(path)
• 重命名文件和目錄
– fs.rename(oldPath, newPath, callback)
– fs.renameSync(oldPath, newPath)
• 監視文件更改寫入
– fs.watchFile(filename[, options], listener)
十九、WEB模塊(WEB服務器):
響應 json:
響應HTML頁面 :
main.js:
index.html:
二十、express框架:
1、什么是express?
express是也一個基於node.js的極簡、靈活的web開發框架。可以實現非常強大的web服務器功能。
2、express的特點:
可以設置中間件響應或過濾http請求;
可以使用路由實現動態網頁,響應不同的http請求;
內置支持ejs模板(默認是jade模板)實現模板渲染生成html;
3、express-generator生成器:
express-generator是express官方團隊為開發者准備的一個快速生成工具,可以非常快速的生成一個基本的express開發框架。
4、express安裝與使用:
1)安裝express-generator生成器;
安裝完成后可以使用express命令。
2)創建項目:
3)安裝依賴:
4)開啟項目
5)測試項目:
打開瀏覽器輸入localhost
二十一、Node.js 連接 MySQL:
安裝驅動:
注意:cnpm install mysql是安裝nodejs的mysql模塊而不是安裝mysql數據庫,你的應用通過這個驅動程序連接並操作mysql中的庫和表。
如果你的電腦中沒有mysql,則請先安裝,相關教程如下:
https://jingyan.baidu.com/article/363872ec2e27076e4ba16fc3.html
在進行數據庫操作前,你需要將以下SQL 文件導入到你的 MySQL 數據庫中。
連接數據庫
數據庫操作( CURD )
查詢數據
將上面我們提供的 SQL 文件導入數據庫后,執行以下代碼即可查詢出數據:
插入數據
更新數據
刪除數據
二十二、其它工具:
nodemon:


