Nodejs入門級基礎


這篇隨筆將會按序記錄如下內容:

  1. NodeJs 簡介 安裝 
  2. NodeJs HTTP 模塊、URL 模塊
  3. CommonJs 和 Nodejs 中自定義模塊
  4. NodeJs FS 模塊
  5. 利用 HTTP 模塊 URl 模塊 PATH 模塊 FS模塊創建一個 WEB 服務器(基礎實戰)
  6. 關於Node.js的非阻塞IO,異步,事件驅動基礎

cnpm淘寶鏡像: npm install -g cnpm --registry=https://registry.npm.taobao.org 

1. NodeJs簡介 安裝 開發工具配置

Nodejs介紹

Node.js 是一個 Javascript 運行環境(runtime)。它讓 JavaScript 可以開發后端程序,實現幾乎其他后端語言實現的所有功能,可以與 PHP、JSP、Python、Ruby 等后端語言平起平坐。
Nodejs 是基於 V8 引擎,V8 是 Google 發布的開源 JavaScript 引擎,本身就是用於 Chrome 瀏覽器的 JS 解釋部分,但是 Ryan Dahl 這哥們,鬼才般的,把這個 V8 搬到了服務器上,用於做服務器的軟件。

Node優勢

I.NodeJs 語法完全是 js 語法,只要懂 JS 基礎就可以學會 Nodejs 后端開發。

這打破了過去 JavaScript 只能在瀏覽器中運行的局面。前后端編程環境統一,可以大大降低開發成本。

II.NodeJs 超強的高並發能力。

Node.js 的首要目標是提供一種簡單的、用於創建高性能服務器及可在該服務器中運行的各種應用程序的開發工具。在 Java、PHP 或者.net 等服務器端語言中,會為每一個客戶端連接創建一個新的線程。而每個線程需要耗費大約 2MB 內存。也就是說,理論上,一個 8GB 內存的服務器可以同時連接的最大用戶數為 4000 個左右,而Node.js 不為每個客戶連接創建一個新的線程,而僅僅使用一個線程。當有用戶連接了,就觸發一個內部事件,通過非阻塞 I/O、事件驅動機制,讓 Node.js 程序宏觀上也是並行的。使用 Node.js,一個 8GB內存的服務器,可以同時處理超過 4 萬用戶的連接。

III.實現高性能服務器。

嚴格地說,Node.js 是一個用於開發各種 Web 服務器的開發工具。在 Node.js 服務器中,運行的是高性能 V8JavaScript 腳本語言,該語言是一種可以運行在服務器端的 JavaScript 腳本語言。那么,什么是 V8 JavaScript 腳本語言呢?該語言是一種被 V8 JavaScript 引擎所解析並執行的腳本語言。V8JavaScript 引擎是由 Google 公司使用 C++語言開發的一種高性能 JavaScript 引擎,該引擎並不局限於在瀏覽器中運行。Node.js 將其轉用在了服務器中,並且為其提供了許多附加的具有各種不同用途的 API。例如,在一個服務器中,經常需要處理各種二進制數據。在 JavaScript 腳本語言中,只具有非常有限的對二進制數據的處理能力,而 Node.js 所提供的 Buffer 類則提供了豐富的對二進制數據的處理能力。另外,在 V8 JavaScript 引擎內部使用一種全新的編譯技術。這意味着開發者編寫的高端的 JavaScript 腳本代碼與開發者編寫的低端的 C語言具有非常相近的執行效率,這也是 Node.js 服務器可以提供的一個重要特性。

Node.js 自身哲學,是花最小的硬件成本,追求更高的並發,更高的處理性能。

Node環境的搭建

下載穩定版本、雙擊下一步下一步安裝。

2. NodeJs HTTP 模塊、URL 模塊

I. Node.js 創建第一個應用

如果我們使用 PHP 來編寫后端的代碼時,需要 Apache 或者 Nginx 的 HTTP 服務器,來處理客戶端的請求相應。不過對 Node.js 來說,概念完全不一樣了。使用 Node.js 時,我們不僅僅在實現一個應用,同時還實現了整個 HTTP 服務器。
1、引入 http 模塊
var http = require("http");
2、創建服務器
接下來我們使用 http.createServer() 方法創建服務器,並使用 listen 方法綁定 8888 端口。函數通過 request, response 參數來接收和響應數據。
復制代碼
var http = require('http');
http.createServer(function (request, response) {
// 發送 HTTP 頭部
// HTTP 狀態值: 200 : OK
//設置 HTTP 頭部,狀態碼是 200,文件類型是 html,字符集是 utf8
response.writeHead(200,{"Content-Type":"text/html;charset=UTF-8"});
// 發送響應數據 "Hello World"
res.end("這是第一個node應用");
}).listen(3000);
復制代碼
3.運行程序
用命令行切換到程序對應目錄。通過 node 命令運行程序。
node xxx.js
你會發現,我們本地寫一個 js,打死都不能直接拖入瀏覽器運行,但是有了 node,我們任何一個 js 文件,都可以通過 node 來運行。也就是說,node 就是一個 js 的執行環境。

II. HTTP 模塊、URL 模塊

Node.js 中,將很多的功能,划分為了一個個 module(模塊)。 Node.js 中的很多功能都是通過模塊實現。
1.HTTP 模塊的使用
復制代碼
//引用模塊
var http = require("http");
//創建一個服務器,回調函數表示接收到請求之后做的事情
var server = http.createServer(function(req,res){
//req 參數表示請求,res 表示響應
console.log("服務器接收到了請求" + req.url);
res.end(); // End 方法使 Web 服務器停止處理腳本並返回當前結果
});
//監聽端口
server.listen(3000);
復制代碼

設置一個響應頭

復制代碼
//引用模塊
var http = require("http");
//創建一個服務器,回調函數表示接收到請求之后做的事情
var server = http.createServer(function(req,res){
//req 參數表示請求,res 表示響應
res.writeHead(200,{"Content-Type":"text/html;charset=UTF8"});//插入響應頭
console.log("服務器接收到了請求" + req.url);
res.end(); // End 方法使 Web 服務器停止處理腳本並返回當前結果
});
//監聽端口
server.listen(3000);
復制代碼
 
現在來看一下 req 里面能夠使用的東西。最關鍵的就是 req.url 屬性,表示用戶的請求 URL 地址。所有的路由設計,都是通過 req.url來實現的。我們比較關心的不是拿到 URL,而是識別這個 URL。識別 URL,用到了下面的 url 模塊

 

2.URL 模塊的使用

url.parse() //解析 URL
url.format(urlObject) //是上面 url.parse() 操作的逆向操作
url.resolve(from, to) //添加或者替換地址

3. CommonJs 和 Nodejs 中自定義模塊

什么是Common.js

JavaScript 是一個強大面向對象語言,它有很多快速高效的解釋器。然而, JavaScript標准定義的 API 是為了構建基於瀏覽器的應用程序。並沒有制定一個用於更廣泛的應用程序的標准庫。CommonJS 規范的提出,主要是為了彌補當前 JavaScript 沒有標准的缺陷。它的終極目標就是:提供一個類似 Python,Ruby 和 Java 語言的標准庫,而不只是停留在小腳本程序的階段。 CommonJS 就是模塊化的標准,nodejs 就是 CommonJS(模塊化)的實現。

Nodejs 中的模塊化

Node 應用由模塊組成,采用 CommonJS 模塊規范。
I.  Node 中,模塊分為兩類:
一類是 Node 提供的模塊,稱為核心模塊;另一類是用戶編寫的模塊,稱為文件模塊。
    • 核心模塊部分在 Node 源代碼的編譯過程中,編譯進了二進制執行文件。在 Node 進程啟動時,部分核心模塊就被直接加載進內存中,所以這部分核心模塊引入時,文件定位和編譯執行這兩個步驟可以省略掉,並且在路徑分析中優先判斷,所以它的加載速度是最快的。如:HTTP 模塊 、URL 模塊、Fs 模塊都是 nodejs 內置的核心模塊,可以直接引入使用。
    • 文件模塊則是在運行時動態加載,需要完整的路徑分析、文件定位、編譯執行過程、速度相比核心模塊稍微慢一些,但是用的非常多。這些模塊需要我們自己定義。接下來我們看一下 nodejs 中的自定義模塊。
II. CommonJS(Nodejs)中自定義模塊的規定
    • 我們可以把公共的功能抽離成為一個單獨的 js 文件作為一個模塊,默認情況下面這個模塊里面的方法或者屬性,外面是沒法訪問的。如果要讓外部可以訪問模塊里面的方法或者屬性,就必須在模塊里面通過 exports 或者 module.exports 暴露屬性或者方法。
    • 在需要使用這些模塊的文件中,通過 require 的方式引入這個模塊。這個時候就可以使用模塊里面暴露的屬性和方法。 
III. 定義使用模塊
復制代碼
// 定義一個 tools.js 的模塊
//模塊定義
var tools = {
sayHello: function() {
return 'hello NodeJS';
},
add: function(x, y) {
return x + y;
}
};
// 模塊接口的暴露
// module.exports = tools;
exports.sayHello = tools.sayHello;
exports.add = tools.add;
復制代碼
var http = require('http');
// 引入自定義的 tools.js 模塊
var tools= require('./tools');
tools.sayHello(); //使用模塊

npm init 生成 package.json

npm init 

package.json內保存了應用信息,比如版本,依賴,環境等。

4. NodeJs FS 模塊

!使用前先引入fs模塊

const fs = require('fs')
1.fs.stat 檢測是文件還是目錄
復制代碼
fs.stat('hello.js', (error, stats) =>{
if(error){
console.log(error)
} else {
console.log(stats)
console.log(`文件:${stats.isFile()}`)
console.log(`目錄:${stats.isDirectory()}`) }
})
復制代碼
2. fs.mkdir 創建目錄
復制代碼
const fs = require('fs')
fs.mkdir('logs', (error) => {
if(error){
console.log(error)
} else {
console.log('成功創建目錄:logs') }
})
復制代碼
3. fs.writeFile 創建寫入文件
fs.writeFile('logs/hello.log', '您好 ~ \n', (error) => {
if(error) {
console.log(error)
} else {
console.log('成功寫入文件') }
})
4. fs.appendFile 追加文件
fs.appendFile('logs/hello.log', 'hello ~ \n', (error) => {
if(error) {
console.log(error)
} else {
console.log('成功寫入文件') }
})
5.fs.readFile 讀取文件
復制代碼
const fs = require('fs')
fs.readFile('logs/hello.log', 'utf8', (error, data) =>{
if (error) {
console.log(error)
} else {
console.log(data)
}
})
復制代碼
6.fs.readdir 讀取目錄
復制代碼
const fs = require('fs')
fs.readdir('logs', (error, files) => {
if (error) {
console.log(error)
} else {
console.log(files)
}
})
復制代碼
7.fs.rename 重命名
復制代碼
const fs = require('fs')
fs.rename('js/hello.log', 'js/greeting.log', (error) =>{
if (error) {
console.log(error)
} else {
console.log('重命名成功') }
})
復制代碼
8. fs.rmdir 刪除目錄
fs.rmdir('logs', (error) =>{
if (error) {
console.log(error)
} else {
console.log('成功的刪除了目錄:logs') }
})
9. fs.unlink 刪除文件
fs.unlink(`logs/${file}`, (error) => {
if (error) {
console.log(error)
} else {
console.log(`成功的刪除了文件: ${file}`) }
})
10. fs.createReadStream 從文件流中讀取數據
復制代碼
const fs = require('fs')
var fileReadStream = fs.createReadStream('data.json')
let count=0;
var str='';
fileReadStream.on('data', (chunk) => {
console.log(`${ ++count } 接收到:${chunk.length}`);
str+=chunk
})
fileReadStream.on('end', () => {
console.log('--- 結束 ---');
console.log(count);
console.log(str);
})
fileReadStream.on('error', (error) => {
console.log(error)
})
復制代碼
11. fs.createWriteStream 寫入文件
復制代碼
var fs = require("fs");
var data = '我是從數據庫獲取的數據,我要保存起來';
// 創建一個可以寫入的流,寫入到文件 output.txt 中
var writerStream = fs.createWriteStream('output.txt');
// 使用 utf8 編碼寫入數據
writerStream.write(data,'UTF8');
// 標記文件末尾
writerStream.end();
// 處理流事件 --> finish 事件
writerStream.on('finish', function() { /*finish - 所有數據已被寫入到底層系統時觸發。*/
console.log("寫入完成。");
});
writerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程序執行完畢");
復制代碼
12. 管道流
管道提供了一個輸出流到輸入流的機制。通常我們用於從一個流中獲取數據並將數據傳遞到另外一個流中。
復制代碼
var fs = require("fs");
// 創建一個可讀流
var readerStream = fs.createReadStream('input.txt');
// 創建一個可寫流
var writerStream = fs.createWriteStream('output.txt');
// 管道讀寫操作
// 讀取 input.txt 文件內容,並將內容寫入到 output.txt 文件中
readerStream.pipe(writerStream);
console.log("程序執行完畢");
復制代碼

5. Node.js 搭建靜態WEB服務器

待更新

 

6. 關於Node.js的非阻塞IO,異步,事件驅動基礎

Nodejs 的單線程 非阻塞 I/O 事件驅動:

在 Java、PHP 或者.net 等服務器端語言中,會為每一個客戶端連接創建一個新的線程。而每個線程需要耗費大約 2MB 內存。也就是說,理論上,一個 8GB 內存的服務器可以同時連接的最大用戶數為 4000 個左右。要讓 Web 應用程序支持更多的用戶,就需要增加服務器的數量,而 Web 應用程序的硬件成本當然就上升了。Node.js 不為每個客戶連接創建一個新的線程,而僅僅使用一個線程。當有用戶連接了,就觸發一個內部事件,通過非阻塞 I/O、事件驅動機制,讓 Node.js 程序宏觀上也是並行的。使用 Node.js,一個 8GB 內存的服務器,可以同時處理超過 4 萬用戶的連接。

Nodejs 回調處理異步:

復制代碼
//正確的處理異步:
function getData(callback){
//模擬請求數據
var result='';
setTimeout(function(){
result='這是請求到的數據';
callback(result);
},200);
}
getData(function(data){
console.log(data);
})
復制代碼

Nodejs events 模塊處理異步:

Node.js 有多個內置的事件,我們可以通過引入 events 模塊,並通過實例化 EventEmitter類來綁定和監聽事件。
復制代碼
// 引入 events 模塊
var events = require('events');
var EventEmitter=new events.EventEmitter(); /*實例化事件對象*/
EventEmitter.on('toparent',function(){
    console.log('接收到了廣播事件');
})
setTimeout(function(){
    console.log('廣播');
    EventEmitter.emit('toparent'); /*發送廣播*/
},1000)
復制代碼

 

本文轉載自:https://www.cnblogs.com/zlforever-young/p/11558943.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM