入門nodejs部署web後端

首先認識一下node.js

Node.js 是一個讓 JavaScript 運行在服務端的開發平臺,它讓 JavaScript 成爲與PHPPythonPerlRuby 等服務端語言平起平坐的腳本語言。發佈於2009年5月,由Ryan Dahl開發,實質是對Chrome V8引擎進行了封裝。

Node.js對一些特殊用例進行優化,提供替代的API,使得V8在非瀏覽器環境下運行得更好。V8引擎執行Javascript的速度非常快,性能非常好。Node.js是一個基於Chrome JavaScript運行時建立的平臺, 用於方便地搭建響應速度快、易於擴展的網絡應用。Node.js 使用事件驅動, 非阻塞I/O 模型而得以輕量和高效,非常適合在分佈式設備上運行數據密集型的實時應用。

以上是百度的定義,node.js就是讓javascript運行在服務端,所以使用的語言就是javascript,它有一個特性,就是上文提到的非阻塞I/O模型,可以簡單的理解爲異步執行,也就是說node.js不會從前到後按順序依次執行代碼指令,而有可能前面的指令還沒執行完畢,後面的代碼就已經開始執行了,這個特性往往會讓新手在初學階段摸不到頭腦,不過沒關係,使用多了,自然就對異步的概念清楚了。

這篇博客就是使用node.js來部署簡單的web後端,實現前後端的通信,接收前端的get、post請求,向前端發送數據、頁面等,node.js的安裝與環境配置,網上很多資源,就不再累述,下面就進入正題。

運行.js程序

首先創建一個.js文件,最簡單的方法就是創建一個文本文件,將後綴改爲.js,也可以用編譯器創建,創建好了,如下:

用編譯器或者記事本等打開,寫入一行命令,如下:

然後打開cmd命令窗口,cd到.js文件所在的目錄,接下來,如果環境配置好了,可以使用node server.js或者省略後綴node server來運行.js程序,如下:

看到已經成功打印出hello了。

node.js中文網,有所有api的用法

架設http服務器

前面是鋪墊,從這裏開始我們就要真正的假設一個服務器了。

 我們一般訪問一個網頁,會從地址欄輸入一個網址

https代表Web瀏覽器和網站服務器之間傳遞信息遵從https協議,以前都是用http協議傳輸,但現在已經逐漸都在使用https了,因爲https比http更加安全。

www.baidu.com就是百度的域名,沒有註冊域名之前,我們可以使用"ip地址:端口號"的形式來訪問,比如https://localhost:8888,localhost即訪問本機,也可以是其他的ip地址。

http模塊

架設http服務器,http模塊是必不可少的。

我們分3步走:

這樣我們就建好了一個最簡單的http服務器,我們運行server.js程序,然後在瀏覽器地址欄裏輸入http://localhost:8888,訪問,

可以看到後端輸出new message說明後端接收到了前端的請求。我們後端監聽的是8888端口,並且前端訪問的也是8888端口,所以當前端向後端發送請求時,後端監聽到8888端口有請求,於是就會調用http服務,打印出new messge,這就是程序執行的過程。

http服務裏面接收兩個參數req和res,req是request的縮寫,res是response的縮寫,一個代表請求,一個代表迴應,前端向後端發送的數據一般在req裏,而後端向前端返回數據時,一般用res向前端返回,具體用法,往下看。

架設路由

路由這個概念是網絡中很重要的一個概念,但具體含義我也解釋不太清楚,在這裏可以簡單理解爲後端不同的分支對應前端不同的請求吧,看一下事例,就能夠非常清晰的解釋了。

req有許多的屬性,感興趣的可以打印一下req,可以看到有非常多的屬性,我們這裏用到一個比較重要的屬性url,url是統一資源定位符,對可以從互聯網上得到的資源的位置和訪問方法的一種簡潔的表示,是互聯網上標準資源的地址。

剛剛我們請求的是http://localhost:8888,接下來我們請求比如http://localhost:8888/index

然後打印req.url,輸出如下: 

可以看到對於不同的請求地址,req.url也是不同的,這意味着我們可以架設不同的分支,來處理不同的請求。事例如下:

再試試請求不同的地址:

很明顯不同的請求,後端進入了不同的分支,並向前端返回不同的消息,這就是架設路由。

我們這裏用到了一個新函數,res.write(),顧名思義,就是寫入數據,而我們的對象是res,也就是前端頁面,所以我們向前端頁面傳送了一串字符數據,注意這裏write()後面一定要跟上end()來結束傳輸,不然前端是收不到數據的,會一直處於等待後端響應的狀態。

解析GET請求,獲取參數

在實際使用中,前端常常會向後端傳送一些數據,我們需要知道,只要是在地址欄裏輸入地址來訪問頁面,都是發送一個GET請求,此時GET請求的參數可以在url中獲取:

地址?後面所接的就是GET請求傳送的數據,下面我們講如何從後端獲取這裏的數據。

爲了解析url,我們需要引入url模塊。

請求圖中url,解析後,返回一個urlobject對象,它的屬性如下:

可以看到參數在query屬性裏,路由則在pathname裏。但是query是以字符串的方式儲存的參數的,使用時不方便,我們可以在url.parse()裏添加第二個參數true,這樣解析時就會自動把參數轉換爲對象了。

fs模塊

fs是file system的簡稱,用於讀寫文件。

下面介紹幾個重要的函數

var fs = require('fs')

fs.exist(path, function (bol) {//功能是判斷一個文件是否存在
    //第一個參數是需要判斷的文件的路徑,爲一個字符串
    //第二個參數是一個回調函數,回調函數的參數爲一個布爾類型,如果爲true則文件存在,否則不存在
})

fs.realpath(path, function (err, realpath) {//功能是把相對路徑轉換爲絕對路徑
    //第一個參數是相對路徑,
    //回調函數的第一個參數是錯誤信息,若成功,則第二個參數保存轉換成功的絕對路徑
})

fs.rename(path, new_name, function (err) {//功能是重命名一個文件
    //第一個參數是需要修改的源文件路徑
    //第二個參數是重新命名的名字
    //回調函數的參數是若修改失敗的錯誤信息
})

fs.readFile(path, coded_format, function (err,data) {//功能是讀一個文件
    //第一個參數路徑是讀取的文件路徑
    //第二個參數是讀取時的編碼格式,如'utf-8'
    //回調函數的參數,err是若錯誤的錯誤信息,data是若成功,讀取的數據
})

fs.writeFile(path, content,operation, function (err) {
    //第一個參數是寫入的文件路徑
    //第二個參數是寫入的內容
    //第三個參數是寫入控制操作,如覆蓋寫入、追加寫入、指定編碼格式等
    //回調函數的參數err指示錯誤信息
})

對於較大的文件,應使用管道流的方式讀寫,管道流與普通的讀寫方式的區別是,普通的讀寫方式,是整讀整寫,一次性操作;而管道流是分塊讀寫,每次傳輸64k大小的數據。管道流的優勢是,如果傳輸過程中出現錯誤,那麼之前已經傳輸的內容不會丟失,下次只要接着傳輸就可以了,而普通讀寫,如果出現錯誤,則這次讀寫的失敗了。不過因爲管道流的分塊讀寫方式,我們需要把收到的數據拼接起來,才能獲得完整數據。

var fs = require('fs')

var stream = fs.createReadStream(path)//創建一個讀取流,參數是讀取的文件的路徑

var data = null
stream.on('data', function (chunk) {
    //爲讀取流綁定讀取事件,每一次讀取都會觸發,chunk的意思是片、塊,就是一次讀取的數據塊
    data += chunk//拼接數據
})
console.log(data)//完整數據

stream.on('end', function () {
    //讀取結束時觸發
})

//數據是buffer類型時,可以用toString()方法轉換成字符串
var fs = require('fs')

var stream = fs.createWriteStream(path)//創建一個寫入流,參數是寫入的文件的路徑

stream.write(content)//通過管道流的方式寫入,參數是寫入內容

readStream.pipe(writeStream)//也可以用這種方式把讀取流的數據寫入寫入流,這種方式與上面一種的區別是,它會等待每次數據寫入完成後,纔會進行下一次讀取,內存利用率高。而上一種方法,讀取速度快於寫入速度,則等待寫入的數據會滯留在內存中,佔用內存。

解析POST請求

post和get請求是前後端交互最重要的請求,post與get請求的區別是,get請求的參數是拼接在url後面的,而post請求的參數卻是在頭部,post請求是通過發送數據包的方式把數據在前端與後端之間傳輸,下面我們就介紹如何把參數從post請求解析出來。

首先準備一個html頁面,做演示用:

請求http://localhost:8888/index.html,後端會向前端發送這個頁面。後端代碼:

在賬號欄和密碼欄填入123,點擊提交,後端顯示如下:

然後把method改爲POST,再請求,後端顯示如下:

參數不能通過與get請求同樣的方法獲取,說明參數放在別的地方。

將後端代碼修改如下,用管道流的方式把數據從req中提取出來:

var http = require('http')
var url = require('url')
var fs = require('fs')

var server = http.createServer(function (req, res) {
   var urlObj = url.parse(req.url,true);
   if(urlObj.pathname=="/index.html"){
       var rs = fs.createReadStream("./index.html");
       var index = null;
       rs.on('data',function(chunk){
           index+=chunk
       })
       
       rs.pipe(res)
   }
   else if(urlObj.pathname=="/login"){
       var data = '';
       req.on('data',function(chunk){
           data+=chunk
       });
       
       req.on('end',function(){
          console.log(data)  
       })
   }
})

server.listen(8888, function () {
    console.log('start server')
})

後端輸出如下:

我們已經成功獲取了POST請求的數據,但是它不是我們想要的格式,我們可以引用一個第三方庫'querystring' :

var qs = require('querystring')

...

req.on('end',function(){
          var queryObj = qs.parse(data)
          console.log(queryObj)  
       })

...

後臺輸出如下:

當我們使用express模塊時,還可以使用body-parser中間件來解析數據,對於body-parser的使用,這篇博客寫的很詳細

https://blog.csdn.net/yanyang1116/article/details/54847560

express模塊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章