Node&Express-讀書筆記(1)

Node.js不是JS應用、而是JS運行平臺css

看到Node.js這個名字,初學者可能會誤覺得這是一個Javascript應用,事實上,Node.js採用C++語言編寫而成,是一個Javascript的運行環境。爲何採用C++語言呢?據Node.js創始人Ryan Dahl回憶,他最初但願採用Ruby來寫Node.js,可是後來發現Ruby虛擬機的性能不能知足他的要求,後來他嘗試採用V8引擎,因此選擇了C++語言。既然不是Javascript應用,爲什麼叫.js呢?由於Node.js是一個Javascript的運行環境。提到Javascript,你們首先想到的是平常使用的瀏覽器,現代瀏覽器包含了各類組件,包括渲染引擎、Javascript引擎等,其中Javascript引擎負責解釋執行網頁中的Javascript代碼。做爲Web前端最重要的語言之一,Javascript一直是前端工程師的專利。不過,Node.js是一個後端的Javascript運行環境(支持的系統包括*nux、Windows),這意味着你能夠編寫系統級或者服務器端的Javascript代碼,交給Node.js來解釋執html

Node.js採用了Google Chrome瀏覽器的V8引擎,性能很好,同時還提供了不少系統級的API,如文件操做、網絡編程等。瀏覽器端的Javascript代碼在運行時會受到各類安全性的限制,對客戶系統的操做有限。相比之下,Node.js則是一個全面的後臺運行時,爲Javascript提供了其餘語言可以實現的許多功能。前端

Node.js採用事件驅動、異步編程,爲網絡服務而設計
事件驅動這個詞並不陌生,在某些傳統語言的網絡編程中,咱們會用到回調函數,好比當socket資源達到某種狀態時,註冊的回調函數就會執行。Node.js的設計思想中以事件驅動爲核心,它提供的絕大多數API都是基於事件的、異步的風格。以Net模塊爲例,其中的net.Socket對象就有如下事件:connect、data、end、timeout、drain、error、close等,使用Node.js的開發人員須要根據本身的業務邏輯註冊相應的回調函數。這些回調函數都是異步執行的,這意味着雖然在代碼結構中,這些函數看似是依次註冊的,可是它們並不依賴於自身出現的順序,而是等待相應的事件觸發。事件驅動、異步編程的設計(感興趣的讀者能夠查閱筆者的另外一篇文章《Node.js的異步編程風格》),重要的優點在於,充分利用了系統資源,執行代碼無須阻塞等待某種操做完成,有限的資源能夠用於其餘的任務。此類設計很是適合於後端的網絡服務編程,Node.js的目標也在於此。在服務器開發中,併發的請求處理是個大問題,阻塞式的函數會致使資源浪費和時間延遲。經過事件註冊、異步函數,開發人員能夠提升資源的利用率,性能也會改善。node

從Node.js提供的支持模塊中,咱們能夠看到包括文件操做在內的許多函數都是異步執行的,這和傳統語言存在區別,並且爲了方便服務器開發,Node.js的網絡模塊特別多,包括HTTP、DNS、NET、UDP、HTTPS、TLS等,開發人員能夠在此基礎上快速構建Web服務器。git

Node是一種新型的web服務器,他的核心理念是事件驅動編程,主要的特色:
1)Node是單線程的
2)它與平臺無關
Express是一個靈活的,簡潔的Nodejs Web程序框架,Express跟Connect有着緊密的聯繫,Connect是一個Node的插件庫,他能不一樣程度上處理web請求,在version 4.0以前,Express一直綁定Connect,在4.0中,Connect以及除了static以外的全部中間件都被去掉了,以便這些中間件能夠獨立升級.
1,hello worldweb

var http = require('http')
http.createServer(function(req,res){
    res.writeHead(200,{'Content-Type':'html/text'})
    var path = req.url
    switch(path){
        case '':
            res.writeHead(200,{'Content-Type':'html/text'})
    }
}).listen(3000)
console.log("out.print successfully...")

2,路由
路由是指向客戶端提供他所發出的請求內容機制。express

var http = require('http')
http.createServer(function(req,res){
    var path = req.url.replace(/\/?(?:\?.*)?$/,'').toLowerCase()//優化url,去掉查詢字符串(?a=b),可選的反斜槓(/*),並變成小寫
    switch(path){
            res.writeHead(200,{'Content-Type':'text/plain'})
            res.end('homepage')
            break
        case'/about':
            res.writeHead(200,{'Content-Type':'text/plain'})
            res.end('about')
            break
        default:
            res.writeHead(200,{'Content-Type':'text/plain'})
            res.end('Not found')
            break
    }
}).listen(3000)
console.log("out.print successfully...")

3,靜態資源服務
用node提供靜態資源只適用於初期的小項目,對於大的項目應該會想到使用Nginx或CDN之類的代理服務器來提供靜態資源。
對於node,咱們先要打開文件,讀取其中的內容,而後將這些內容發送給瀏覽器。npm

var http = require('http')
var  fs = require('fs')//FS(File System)文件系統操做函數
function serveStaticFile(res,path,contentType,responseCode){//輔助函數
    if(!responseCode) responseCode = 200
    fs.readFile(__dirname+path,function(err,data){//__dirname是一個全局變量,注意是2個下滑線"_"表示解析正在執行腳本所在的目錄,fs.readFile是一個讀取文件的異步方法
      if(err){
          res.writeHead(500,{'Content-Type':'text/plain'})
          res.end('500 -Internal Error')
      }else{
          res.writeHead(responseCode,{'Content-Type':contentType})
          res.end(data)
      }
    })
}
http.createServer(function(req,res){
    var path = req.url.replace(/\/?(?:\?.*)?$/,'').toLowerCase()//優化url,去掉查詢字符串(?a=b),可選的反斜槓(/*),並變成小寫
    switch(path){
        case'':
             serveStaticFile(res,'/public/home.html','text/html')
            break
        case'/about':
             serveStaticFile(res,'/public/about.html','text/html')
            break
        case'/img':
             serveStaticFile(res,'/public/img/logo.jpg','image/jpeg')
            break
        default:
            serveStaticFile(res,'/public/404.html','text/html',404)
            break
    }
}).listen(3000)
console.log("out.print successfully...")

Express框架
1,腳手架:大多數的項目都須要必定數量的套路化代碼,爲了節約時間避免寫重複代碼,最通用的方法就是建立一個通用的項目骨架,每個寫新的項目只須要用這個骨架,或是這個模板。express就是借鑑了RoR,提供了一個生成腳手架的工具,從而能夠開始一個新的express項目。編程

2,安裝express
npm install --save express
--save選項是爲了保證會更新package.json,由於node_modules隨時均可以生成,因此咱們不會把這個目錄保存到咱們的代碼庫中,爲了這一點咱們能夠建立一個.gitignore
node 入口文件 projectName.jsjson

引入express框架
var express = require('express')
var app = express()
設置監聽端口
var app = express()
app.set('port',process.env.PORT||3000)
配置404
app.use(function(req,res){
    res.type('text/plain')
    res.status(404)
    res.send('404 - Not Found')
})
配置500
//定製500
app.use(function(err,req,res,next){
    console.error(err.stack)
    res.type('text/plain')
    res.status(500)
    res.send('500 - Server Error')
})
監聽端口而且在控制檯print
app.listen(app.get('port'),function(){
    console.log('http://localhost:'+app.get('port')+';')
})

在404處理器以前加上路由:

app.get('/',function(req,res){
    res.type('text/plain')
    res.send('mikeProject')
})
app.get('/about',function(req,res){
    res.type('text/plain')
    res.send('this is about mikes project')
})
//定製404頁面
app.use(function(req,res,next){
    res.type('text/plain')
    res.status(404)
    res.send('404 - Not Found')
})

在express官方文檔中寫道app.verp,後面的http動詞就是方法(get/post),這裏的app.get是咱們添加路由的方法,這個方法有2個參數:一個路徑和一個函數
app.verb幫咱們作了不少的工做,默認忽略了大小寫或反斜槓而且進行匹配的時候不考慮查詢字符串。
res.type:設置響應頭Conten-Type
app.use:這是express添加中間件的一種方法
執行順序:express中,路由和中間件的添加順序很是的重要,注意執行的順序。
3,視圖和佈局
在這裏有一個新的視圖佈局,也就是視圖引擎叫handlebars,爲了支持handlebars,咱們必須使用相關的包:

npm install --save express3-handlebars
var express = ('exrpess');//引入express框架
var app = express();
//設置handlerbars的視圖引擎
var handlebars = require('express3-handlebars').create({defaultLayout:'main'});//設置爲默認的視圖引擎
app.engine('handlebars',handlebars.engine);
app.set('view engine','handlebars')

以上代碼對express進行了配置,將其做爲默認的視圖引擎,接下來建立視圖目錄:views
將每個公用的html代碼寫在母版頁裏面,下面是母模板的內容:

main.handlebars
<!doctype html>
<html>
  <head>
    <title>Mike's internet</title>
  </head>
  <body>
    {{{body}}}
  </body>
</html>

{{{body}}}表達式表明每一個html表達式都會被這個body取代,defaultLayout:'main'
.handlebars和.hbs互用。注意{{{body}}}是三個大括號,而不是兩個。
設置視圖,更換路由:

app.get('/',function(req,res){
    res.render('home')
})
app.get('/about',function(req,res){
    res.render('about')
})
//定製404頁面
app.use(function(req,res,next){
    res.status(404)
    res.render('404')
})
//定製500
app.use(function(err,req,res,next){
    console.error(err.stack)
    res.status(500)
    res.render('500')
})

文件排列
注意,視圖引擎默認會返回text/html的內容和200狀態
4,視圖和靜態文件
express靠中間件處理靜態文件和視圖。
static中間件能夠將一個或多個目錄指派爲包含靜態資源的目錄,其中的資源不通過中間任何的特殊處理,直接發送到客戶端(pic,css,js...),至關於給你要發的靜態文件建立一個路由.
app.use(express.static(_dirname+'/public'))
問題:
發現引用靜態資源引用不了,不知道什麼緣由.
答案:可能與電腦的配置有關係,64位的,電腦配置好一些的就能夠打印出來.

app.use(express.static(__dirname+'/public'))

<body>
<header><img src="/img/logo.jpg" alt="mike"></header>
    {{{body}}}
</body>

5,視圖中的動態內容
視圖並不僅是一種傳遞靜態的html的複雜方式,視圖真正強大之處在於它能夠包含動態的信息.
請看下面的代碼:

首先定義你要顯示的動態數據:
//定義要在視圖中動態顯示的數據
var mikes=["mikes11111111",
"mikes22222222222",
"mikes3333333333",
"mikes444444444",
"mikes55555555555"]
//從新修改路由
app.get('/about',function(req,res){
    //res.render('about')
    var mikeNumber = mikes[Math.floor(Math.random()*mikes.length)]
    res.render('about',{mike:mikeNumber})
})
//修改視圖
<blockquote>{{{mike}}}</blockquote>

顯示內容以下:
沒刷新一次,自動更改顯示的數量:
動態顯示
6,Node模塊
Node模塊和npm包是兩個相互關聯但又是彼此不一樣的概念。Node模塊就像他的名字同樣,提供一個模塊化和封裝的機制,Npm包則提供了一種存儲,版本化和應用的項目,可是不限於模塊的標準範式。好比,express做爲模塊引入:
var express = require('express');
require是一個用來引入模塊的函數。
建立一個包含模塊的目錄:
Lib
./lib/fortune.js

var moneyCookies= [//數組moneyCookies是被徹底隱藏起來的,由於沒有暴露在exports上面
    "Do you want money?",
    "I have 5$,please keep it.",
    "you are welcome,you can have it."
]

exports.getMoney = function(){//若是你想讓一個東西在模塊外可見,那就必須把它加到exports上面
    var idm = Math.floor(Math.random()*moneyCookies.length);
    return moneyCookies[idm]
}

var fortune = require('./lib/fortune.js')//引入模塊

app.get('/about',function(req,res){
    //res.render('about')
    // var mikeNumber = mikes[Math.floor(Math.random()*mikes.length)]
    // res.render('about',{mike:mikeNumber})
    res.render('about',{ fortune: fortune.getMoney()});
});
git add -A
git commit -m "commit for updating about module."

7,頁面測試
爲了把測試真正嵌入到頁面中,是爲了作一個頁面的時候,在瀏覽器中一加載頁面就能夠立刻發現全部的錯誤。這裏須要引入一個測試的框架 mocha
npm install --save-dev mocha
--save-dev instead of --save,是告訴npm把這個包放在開發依賴中,不要放在運行依賴中,這樣在部署依賴的時候能夠減小項目的依賴項,由於mocha要作bowser中運行,因此將放到public目錄中,建立子目錄:public/vendor
另外,測試還須要一個assert/expect函數,node中有這個函數,bowser中沒有,因此:
npm install --save-dev chai
而後把chai.js放到public/vendor裏面

爲了避免影響網站的速度並且還要看到測試的結果,得準備一個路由,放在因此路由以前:

node相關問題: 新版的express中已經不包含bodyparser解決辦法:1,npm install body-parser2,var bodyParser = require('body-parser')3,把app.use(express.bodyParser())替換成app.use(bodyParser.urlencoded({ extended: false }))4,在node中寫理由的時候,因爲post過來的數據須要格式化,若是發現entity undefined,就須要將app.use(bodyParser.urlencoded({ extended: true })) 該成true 就行了

相關文章
相關標籤/搜索