這有一篇Nodejs+Express的初級指南……

小樣兒吧你發表於2019-02-16

寫在前面:

這是小生跟著視訊學習的總結,文末貼的有地址,很容易上手,自己都跟著敲了一遍,覺得不錯,
值得總結安利一下,歡迎糾錯……

一、 Nodejs建立第一個應用

  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("哈哈哈哈,我買了一個 iPhone" + (1+2+3) + "s"); }).listen(8888 );
// 終端列印如下資訊
console.log(`Server running at http://127.0.0.1:8888/`);
  1. 執行程式

    node server.js

二、HTTP模組, URL模組

2.1 HTTP 模組的使用

//引用模組
var http = require("http");
//建立一個伺服器,回撥函式表示接收到請求之後做的事情
var server = http.createServer(function(req,res){ //req 參數列示請求,res 表示響應
// 設定一個響應頭
res.writeHead(200,{"Content-Type":"text/htm l;c harset=UTF8"});

console.log("伺服器接收到了請求" + req.url);

res.end(); // End 方法使 Web 伺服器停止處理指令碼並返回當前結果
});
//監聽埠
server.listen(3000,"127.0.0.1");

2.2、URL 模組的使用


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

  1. url.format()

  1. url.resolve()

三、 Nodejs 自啟動工具 supervisor

supervisor 會不停的 watch 你應用下面的所有檔案,發現有檔案被修改,就重新載入程式檔案這樣就實現了部署,修改了程式檔案後馬上就能看到變更後的結果。麻麻再也不用擔心我的重啟 nodejs 了!

  1. 首先安裝 supervisor

       npm install -g supervisor
    
  2. 使用 supervisor 代替 node 命令啟動應用

三、 Nodejs中的 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()}` ) 
    }
})
  1. fs.mkdir 建立目錄
const fs = require(`fs`)
fs.mkdir(`logs`, (error) => { 
    if (error){
        console .log(error)
    } else {
        console .log(`成功創 建目錄:logs` )
    }
})
  1. fs.writeFile 建立寫入檔案
fs.writeFile(`logs/hello.log`, `您好 ~ 
`, (error) => {
    if(error) {
        console .log(error)
    } else {
        console .log(`成功寫入檔案` )
    }
})
  1. fs.appendFile 追加檔案
 fs.appendFile(`logs/hello.log`, `hello ~ 
`, (error) => { 
     if(error) {
        console .log(error) } 
    else {
        console .log(`成功寫入檔案` ) 
    }
})
  1. fs.readFile 讀取檔案
const fs = require(`fs`)
fs.readFile(`logs/hello.log`, `utf8`, (error, data) =>{ 
    if (error) {
        console .log(error) 
    } else {
        console .log(data) 
    }
})
  1. fs.readdir 讀取目錄
const fs = require(`fs`)
fs.readdir(`logs`, (error, files) => { 
    if (error) {
        console .log(error)
    } else {
        console .log(files)
    } 
})
  1. fs.rename 重新命名
const fs = require(`fs`)
fs.rename(`js/hello.log`, `js/greeting.log`, (error) =>{
    if (error) {
        console .log(error)
    } else {
        console .log(` 重新命名成功` )
    } 
})
  1. fs.rmdir 刪除目錄
fs.rmdir(`logs`, (error) =>{
    if (error) {
        console .log(error)
    } else { 
        console.log(`成功的刪除了目錄:logs`)
    } 
})
  1. 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. 管道流 管道提供了一個輸出流到輸入流的機制。
通常我們用於從一個流中獲取資料並將資料傳遞到另外一個流中。

![](https://user-gold-cdn.xitu.io/2018/12/14/167acf76097adf62?w=552&h=426&f=png&s=31527)
如上面的圖片所示,我們把檔案比作裝水的桶,而水就是檔案裡的內容,我們用一根管子(pipe )連線兩個桶使得水從一個桶流入另一個桶,這樣就慢慢的實現了大檔案的複製過程。以下例項我們通過讀取一個檔案內容並將內容寫入到另外一個檔案中。

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(“程 序執行完畢” );

### 四、 Nodejs 建立一個 WEB 伺服器。
1. server.js

// 引入http模組
var http = require(`http`);
// 引入fs模組
var fs = require(`fs`);
// 引入path模組
var path = require(`path`);
// 引入url模組
var url = require(`url`);
// 引入自定義的解析模組;
var mime = require(`./model/getMimeFile.js`);
http.createServer(function (req,res) {

<!-- 處理請求地址,獲取請求的pathname  -->
var pathName = url.parse(req.url).pathname;
<!-- 設定響應頭 根據檔案字尾設定不同的Content-Type,讓瀏覽器解析該檔案 -->
res.writeHead(200, {"Content-Type": " " + mime.getMime(fs, path.extname(pathName))+ "; charset=utf-8"});

if(pathName == `/`) pathName = `/index/html`;
if(pathName !== `/favicon.ico`) {
    // 檔案操作去讀取static下面的index.html
    fs.readFile(`static/`+pathName,function (err,data) {
        if(err){
            fs.readFile(`static/404.html`,function (err,data404) {
                res.write(data404);
                res.end();
            })
        } else {
            // console.log(data);
            res.write(data);
            res.end();
        }
    })
}

}).listen(`8002`);

2.  getMimeFile.js 

exports.getMime = function (fs,extname) {

var data = fs.readFileSync(`./mime.json`);
var Mimes = JSON.parse(data.toString())
return Mimes[extname] || `text/html`;

}

### 五、 Nodejs 的非阻塞 I/O、非同步、事件驅動
1. Nodejs的單執行緒 非阻塞I/O事件驅動

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

2. Nodejs 回撥處理非同步

//正確的處理非同步:
function getData(callback){ //模擬請求資料

var result=``; 
setTimeout(function (){
    result=`這是請求到的 資料`; 
    callback(result);
},200); 

}
getData(function(data){

console.log(data);

})

3. Nodejs events 模組處理非同步

// 引入 events 模組
var events = require(`events`);
var EventEmitter = new events.EventEmitter() ; /例項化事件物件/
EventEmitter.on(`toparent`,function(){

console.log(`接收到了廣播事件`);

})
setTimeout(function (){

console.log(`廣播`);
EventEmitter.emit(`toparent`); /*傳送廣播*/ 

},1000)

### 六、 Nodejs的 ejs 模板引擎 

1. 路由      
官方解釋:       
路由(Routing)是由一個 URI(或者叫路徑)和一個特定的 HTTP 方法(GET、POST 等)組成 的,涉及到應用如何響應客戶端對某個網站節點的訪問。


![](https://user-gold-cdn.xitu.io/2018/12/14/167ad0dc9d1bfc6c?w=800&h=468&f=png&s=47406)

2.  初識 EJS 模組引擎
 
文件:  https://www.npmjs.com/package/ejs     
安裝 :  

    npm install ejs –save     /     cnpm install ejs --save

 Nodejs中使用:
 
 
    ejs.renderFile(filename, data, options, function(err, str){ 
        str => Rendered HTML string
    });
    
EJS 常用標籤

 * <%%>流程控制標籤
 * <%=%>輸出標籤(原文輸出HTML標籤) 
 * <%-%>輸出標籤(HTML會被瀏覽器解析)
<a href="<%= url %>"><img src="<%= imageURL %>" alt=""></a><ul>
<ul>
    <% for(var i = 0 ; i < news.length ; i++){ %> 
        <li> <%= news[i] %> </li> 
    <% } %>
</ul>
3.  Get、Post

**超文字傳輸協議(HTTP)的設計目的是保證客戶端機器與伺服器之間的通訊。<br/>在客戶端和伺服器之間進行請求-響應時,兩種最常被用到的方法是:GET 和 POST。<br/>
GET - 從指定的資源請求資料。(一般用於獲取資料)<br/>
POST - 向指定的資源提交要被處理的資料。(一般用於提交資料)**

獲取 GET 傳值:

   var urlinfo = url.parse(req.url,true); 
   urlinfo.query();
獲取 POST 傳值:

var postData = “; // 資料塊接收中
req.on(`data`, function (postDataChunk) {

postData += postDataChunk;

});
// 資料接收完畢,執行回撥函式
req.on(`end`, function () {

try {
    postData = JSON.parse(postData); 
} 
catch (e) { }
req.query = postData;
console.log(querystring .parse(postData));

});

## 七、 MongoDb 資料庫介紹、安裝、使用

   1. 資料庫和檔案的主要區別

1、 資料庫有資料庫表、行和列的概念,讓我們儲存運算元據更方便
2、 資料庫提供了非常方便的介面,可以讓 nodejs、php java .net 很方便的實現增加修改刪除功能。

2. NoSql 介紹    

NoSQL(NoSQL = Not Only SQL ),意即“不僅僅是 SQL”,
它指的是非關係型的資料庫,是以key-value形式儲存,和傳統的關係型資料庫不一樣,
不一定遵循傳統資料庫的一些基本要求.

3. 什麼時候建議使用 NoSql

1、對資料庫高併發讀寫的需求
2、對海量資料的高效率儲存和訪問的需求
3、對資料庫的高可擴充套件性和高可用性的需求

4. NoSql 和傳統資料庫簡單對比

非結構型資料庫。沒有行、列的概念。用 JSON 來儲存資料。
集合就相當於“表 ”,文件就相當於“行”。


![](https://user-gold-cdn.xitu.io/2018/12/24/167df3506d17fbb7?w=535&h=348&f=png&s=59755)

5. mongodb的使用方法     
 i. [mongodb的安裝方法](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/);     
 ii.  開啟 mongodb服務:要管理資料庫,必須先開啟服務,然後進行資料庫的相關操作      
 iii. mongodb的常用指令 

     查詢 (find)    
     增加 (insert)  
     修改 (update)  
     刪除(remove)
檢視所有資料庫列表    show dbs
使用資料庫、建立 資料庫    use student  (student代表 data_base_name);

插入(增加)一條資料    db.student.insert({“name”:”xiaoming”});
db.表名.insert({"name":"zhangsan"}); student 集合名稱(表)

顯示當前的資料集合(mysql 中叫表)    show collections
刪除資料庫,刪除當前所在的資料庫    db.dropDatabase();
刪除集合,刪除指定的集合 刪除表     db.user.drop();

1、查詢所有記 錄
db.userInfo.find();
相當於:select* from userInfo;

2、查詢 age > 22 的記錄 db.userInfo.find({age: {$gt: 22}});
相當於:select * from userInfo where age >22;

3、查詢 age < 22 的記錄
db.userInfo.find({age: {$lt: 22}}); 
相當於:select * from userInfo where age <22; 

4、查詢 age >= 25 的記錄
db.userInfo.find({age: {$gte: 25}}); 
相當於:select * from userInfo where age >= 25;

5、查詢 age <= 25 的記錄 
db.userInfo.find({age: {$lte: 25}});

6. 按照年齡排序 1 升序 -1 降序 
升序: db.userInfo.find().sort({age: 1}); 
降序: db.userInfo.find().sort({age: -1});

7. 查詢前 5 條資料 db.userInfo.find().limit(5 ); 
   相當於:selecttop 5 * from userInfo;

修改資料  
查詢名字叫做小明的,把年齡更改為 16 歲:
db.student.update({"name":"小明"},{$set:{"ag e":16}});

刪除資料
db.collectionsNames.remove( { "borough": "Manhattan" } )
db.users.remove({age: 132});

```

八、 express的介紹

1. express的安裝使用

npm install express –save 
demo:
    var express=require(`express`);  /*引入 express*/
    var app=newexpress(); /*例項化express 賦值給app*/
    //配置路由 匹配 URl 地址實現不同的功能
    app.get(`/`,function(req,res){ 
        res.send(`首頁`);
    }) 
    app.get(`/search`,function(req,res){
        res.send(`搜尋`); //?keyword=華為手機&enc=utf-8&suggest=1.his.0.0&wq
    })
    app.get(`/login`,function(req,res){ 
        res.send(`登入`);
    }) 
    app.get(`/register`,function(req,res){
        res.send(`註冊`);
    }) 
    app.listen(3000,"127.0.0.1");

2. Express 框架中的路由


當用 get 請求訪問一個網址的時候,做什麼事情:
app.get("網址",function(req,res){

});

當用 post 訪問一個網址的時候,做什麼事情:
app.post("網址",function(req,res){

});
// user 節點接受 PUT 請求
app.put(`/user`, function (req, res) {
    res.send(`Got a PUT request at /user`); 
});

// user 節點接受 DELETE 請求 
app.delete(`/user`, function (req, res) {
   res.send(`Got a DELETE request at /user`); 
});

動態路由配置:
"/user/:id "
app.get( ,function(req,res){ 
    var id = req.params["id"];
    res.send(id); 
});
路由的正則匹配:(瞭解)
 app.get(`/ab*cd`, function(req, res) { 
    res.send(`ab*cd`);
});

路由裡面獲取 Get 傳值
/news?id=2&sex=nan

app.get(`/news, function(req, res) { 
    console.log(req.query);
});

#### 3、Express 框架中 ejs 的安裝使用:

i. npm install ejs --save-dev   // 安裝

ii. Express 中 ejs 的使用:

var express = require("express");
var app = express();
app.set("view engine","ejs");
app.get("/",function(req,res){ });
res.render("news",{
    "news" : ["我是小新聞啊","我也是啊","哈哈哈哈"]
}); app.listen(3000);

iii. 指定模板位置 ,預設模板位置在 views
 
 app.set(`views`, __dirname + `/views`);
 
iv. Ejs 字尾修改為 Html
這是一個小技巧,看著.ejs 的字尾總覺得不爽,使用如下方法,可以將模板檔案的字尾換成我們習慣的.html。

1.在 app.js 的頭上定義 ejs:,程式碼如下:
var ejs = require(`ejs`);
2.註冊 html 模板引擎程式碼如下: 
app.engine(`html`,ejs.__express);
3.將模板引擎換成 html程式碼如下:
app.set(`view engine`, `html`);
4.修改模 板檔案的字尾為 .html。

4. 利用 Express.static 託管靜態檔案

1、如果你的靜態資源存放在多個目錄下面,你可以多次呼叫 express.static 中介軟體:

app.use(express.static(`public`));

現在,public目錄下面的檔案就可以訪問了

2、如果你希望所有通過 express.static 訪問的檔案都存放在一個“虛擬(virtual)”目 錄(即目錄根本不存在)下面,可以通過為靜態資源目錄指定一個掛載路徑的方式來實現

app.use(`/static`, express.static(`public`));

現在,你就可以通過帶有 “/static” 字首的地址來訪問 public 目錄下 面的檔案了。

5、 Express 中介軟體 (powerful function)

  1. 應用級中介軟體

  1. 路由中介軟體

  1. 錯誤處理中介軟體

  1. 內建中介軟體

  1. 第三方中介軟體
body-parser    獲取post提交的資料  

6、 獲取 Get Post 請求的引數

● GET 請求的引數在 URL 中,在原生 Node 中,需要使用 url 模組來識別引數字串。在Express 中,不需要使用 url 模組了。可以直接使用 req.query 物件。

● POST 請求在 express 中不能直接獲得,可以使用 body-parser模組。使用後,將可以用req.body得到引數。但是如果表單中含有檔案上傳,那麼還是需要使用 formidable 模組。

var express = require(`express`)
var bodyParser = require(`body-parser`)
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.use(function (req, res) { 
    res.setHeader(`Content-Type`, `text/plain`) 
    res.write(`you posted:
`)
    res.end(JSON.stringify(req.body, null, 2))
})

知識點大概總結這麼多,也算是給前段時間的學習做了一個總結,省得學點,忘點[捂臉?‍♀️]

GitHub地址: node+express;
歡迎交流學習……

宣告:知識點總結是跟著 大地老師的node視訊

一點點學習的,整個課程還是很詳細的,有興趣的可以下載下來自學……

相關文章