1. 程式人生 > >Node.js Express 框架學習

Node.js Express 框架學習

轉載:http://javascript.ruanyifeng.com/nodejs/express.html#toc0

感覺很牛的樣子,不過覺得對初學者沒太大用,裡面很多例子用的api都沒有詳細的說明。為了學習備份,所以拷貝過來。

Express框架

來自《JavaScript 標準參考教程(alpha)》,by 阮一峰

目錄

概述

Express是目前最流行的基於Node.js的Web開發框架,提供各種模組,可以快速地搭建一個具有完整功能的網站。

Express的上手非常簡單,首先新建一個專案目錄,假定叫做hello-world。

$ mkdir hello-world

進入該目錄,新建一個package.json檔案,內容如下。

{
  "name": "hello-world",
  "description": "hello world test app",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "4.x"
  }
}

上面程式碼定義了專案的名稱、描述、版本等,並且指定需要4.0版本以上的Express。

然後,就可以安裝了。

$ npm install

安裝了Express及其依賴的模組以後,在專案根目錄下,新建一個啟動檔案,假定叫做index.js。

var express = require('express');
var app = express();

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

app.listen(8080);

上面程式碼執行之後,訪問http://localhost:8080,就會在瀏覽器中開啟當前目錄的public子目錄。如果public目錄之中有一個圖片檔案my_image.png,那麼可以用http://localhost:8080/my_image.png訪問該檔案。

你也可以在index.js之中,生成動態網頁。

// index.js

var express = require('express');
var app = express();
app.get('/', function (req, res) {  
    res.send('Hello world!');
});
app.listen(3000);  

然後,在命令列下執行下面的命令,就可以在瀏覽器中訪問專案網站了。

node index

預設情況下,網站執行在本機的3000埠,網頁顯示Hello World。

index.js中的app.get用於指定不同的訪問路徑所對應的回撥函式,這叫做“路由”(routing)。上面程式碼只指定了根目錄的回撥函式,因此只有一個路由記錄,實際應用中,可能有多個路由記錄。這時,最好就把路由放到一個單獨的檔案中,比如新建一個routes子目錄。

// routes/index.js

module.exports = function (app) {  
    app.get('/', function (req, res) {  
        res.send('Hello world');
    });
};

然後,原來的index.js就變成下面這樣。

// index.js

var express = require('express');  
var app = express();  
var routes = require('./routes')(app);  
app.listen(3000);  

執行原理

底層:http模組

Express框架建立在node.js內建的http模組上。 http模組生成伺服器的原始程式碼如下。

var http = require("http");

var app = http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end("Hello world!");
});

app.listen(3000, "localhost");

上面程式碼的關鍵是http模組的createServer方法,表示生成一個HTTP伺服器例項。該方法接受一個回撥函式,該回調函式的引數,分別為代表HTTP請求和HTTP迴應的request物件和response物件。

對http模組的再包裝

Express框架的核心是對http模組的再包裝。上面的程式碼用Express改寫如下。

var express = require('express');
var app = express();
app.get('/', function (req, res) {  
    res.send('Hello world!');
});
app.listen(3000);  

var express = require("express");
var http = require("http");

var app = express();

app.use(function(request, response) {
  response.writeHead(200, { "Content-Type": "text/plain" });
  response.end("Hello world!\n");
});

http.createServer(app).listen(1337);

比較兩段程式碼,可以看到它們非常接近,唯一的差別是createServer方法的引數,從一個回撥函式變成了一個Epress物件的例項。而這個例項使用了use方法,載入了與上一段程式碼相同的回撥函式。

Express框架等於在http模組之上,加了一箇中間層,而use方法則相當於呼叫中介軟體。

什麼是中介軟體

簡單說,中介軟體(middleware)就是處理HTTP請求的函式,用來完成各種特定的任務,比如檢查使用者是否登入、分析資料、以及其他在需要最終將資料傳送給使用者之前完成的任務。它最大的特點就是,一箇中間件處理完,再傳遞給下一個中介軟體。

node.js的內建模組http的createServer方法,可以生成一個伺服器例項,該例項允許在執行過程中,呼叫一系列函式(也就是中介軟體)。當一個HTTP請求進入伺服器,伺服器例項會呼叫第一個中介軟體,完成後根據設定,決定是否再呼叫下一個中介軟體。中介軟體內部可以使用伺服器例項的response物件(ServerResponse,即回撥函式的第二個引數),以及一個next回撥函式(即第三個引數)。每個中介軟體都可以對HTTP請求(request物件)做出迴應,並且決定是否呼叫next方法,將request物件再傳給下一個中介軟體。

一個不進行任何操作、只傳遞request物件的中介軟體,大概是下面這樣:

function uselessMiddleware(req, res, next) { 
    next();
}

上面程式碼的next為中介軟體的回撥函式。如果它帶有引數,則代表丟擲一個錯誤,引數為錯誤文字。

function uselessMiddleware(req, res, next) { 
    next('出錯了!');
}

丟擲錯誤以後,後面的中介軟體將不再執行,直到發現一個錯誤處理函式為止。

use方法

use是express呼叫中介軟體的方法,它返回一個函式。下面是一個連續呼叫兩個中介軟體的例子。

var express = require("express");
var http = require("http");

var app = express();

app.use(function(request, response, next) {
  console.log("In comes a " + request.method + " to " + request.url);
  next();
});

app.use(function(request, response) {
  response.writeHead(200, { "Content-Type": "text/plain" });
  response.end("Hello world!\n");
});

http.createServer(app).listen(1337);

上面程式碼先呼叫第一個中介軟體,在控制檯輸出一行資訊,然後通過next方法,呼叫第二個中介軟體,輸出HTTP迴應。由於第二個中介軟體沒有呼叫next方法,所以不再request物件就不再向後傳遞了。

使用use方法,可以根據請求的網址,返回不同的網頁內容。

var express = require("express");
var http = require("http");

var app = express();

app.use(function(request, response, next) {
  if (request.url == "/") {
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.end("Welcome to the homepage!\n");
  } else {
    next();
  }
});

app.use(function(request, response, next) {
  if (request.url == "/about") {
    response.writeHead(200, { "Content-Type": "text/plain" });
  } else {
    next();
  }
});

app.use(function(request, response) {
  response.writeHead(404, { "Content-Type": "text/plain" });
  response.end("404 error!\n");
});

http.createServer(app).listen(1337);

上面程式碼通過request.url屬性,判斷請求的網址,從而返回不同的內容。

除了在回撥函式內部,判斷請求的網址,Express也允許將請求的網址寫在use方法的第一個引數。

app.use('/', someMiddleware);

上面程式碼表示,只對根目錄的請求,呼叫某個中介軟體。

因此,上面的程式碼可以寫成下面的樣子。

var express = require("express");
var http = require("http");

var app = express();

app.use("/", function