nodejs之express中間件

前言

目前最主流的nodejs框架應該就是express和koa了,兩者都是同一個團隊開發的。koa更新一點,而且一些設計思想要比express更成熟,不過仍有大量的項目在使用express。
做者對於express框架的定義爲「==基於 Node.js 平臺,快速、開放、極簡的 Web 開發框架==」。說明express框架自己並無太多功能,而其大多功能都是經過中間件實現的。因而可知中間件在express中的重要性。html

何爲中間件?

當客戶端的請求到達服務器後,nodejs會爲請求建立一個請求對象叫request,該對象上包含了請求的信息以及客戶端傳來的數據。同時也會建立一個響應對象-response,響應對象主要負責將服務器處理的結果返回給客戶端。那麼在服務端響應結果以前就能夠插入多箇中間件。中間件就能夠理解成一個對請求進行過濾和預處理的東西,但他不會直接對客戶端進行響應,而是將處理以後的結果向下傳遞,這也就是爲何能夠插入多箇中間件了。node

在早先的express版本中,中間件使用了Connect中間件框架,3.0版本的express就移除了除‘express.static’外的所有內置中間件,而在4.0版本的express框架中已經不在依賴Connect。能夠說新版的express是一個獨立的路由和中間件的web框架。web

使用中間件

除了使用express.static外的其餘中間件都須要安裝,
npm i <MiddleWare-name> -D
而後在應用中引入中間件:const mod = require('MiddleWare-name');
按照文檔描述使用中間件:server.use(……);express

下面來看看中間件具體的使用npm

express.static
先來看惟一一個express內置的中間件——static,static中間件是用來處理文件請求的。數組

const express = require('express');

let server = express();
server.listen(8080);

server.get('/reg', (req, res, next) => {
  res.send('ok');
});

server.use(express.static('./static/'));

經過server.use使用中間件,在express.static中傳入文件路徑,在客戶端發起文件請求時,服務器就會在該路徑下查找對應文件。
注意一點,該中間件通常放到最後使用,由於若是放在路由以前,那麼一旦有與接口名字相同的文件請求時,就會先請求文件,這樣就不會走到路由中去了。瀏覽器

body-parser
body-parser是幫助解析post數據的中間件,首先須要安裝中間件
npm i body-parser -D服務器

const express = require('express');
// 1
const body = require('body-parser');

let server = express();
server.listen(8080);

// 2
server.use(body.urlencoded({
  extended: false // 是否開啓擴展模式
}));

// 3
server.post('/reg', {req, res} => {
    let { name, pwd } = req.body;
    res.send('ok');
})
  1. 引入中間件;
  2. 這個中間件的使用就要放到路由以前了,由於它是對請求數據的處理;
  3. 使用了該中間件後,請求對象req上就會多出一個body屬性,body屬性裝載的就是請求的數據。經過body就能夠拿到請求的參數;

到這裏咱們演示兩個比較重要和經常使用的第三方中間件,掌握如何使用中中間件以後(就是調用"server.use(...)" )。其餘第三方中間件的使用就大同小異了,至於爲何express.static中間件是調用express.static(),而body-parser中間件是調用body.urlencoded(),這就是做者要求的了,具體調用方式和配置參數還要參考文檔。框架

next方法

express的中間件模式與koa的是不同的,koa是洋蔥型,express是直線型。
在express中間件函數中有三個參數,分別是req、res、next。前兩個參數前面有提到過。而最後一個參數next是一個方法,由於一個應用中可使用多箇中間件,而要想運行下一個中間件,那麼上一個中間件必須運行next()。koa

其實express中間件的原理很簡單,express在內部維護一個數組,這個數組盛放的是在發出響應以前要執行的全部函數,也能夠理解爲中間件數組,每一次use之後,傳進來的中間件就會放到到數組中,執行完畢後調用next方法執行數組的下一項,若是沒有下一項,那麼調用就會終止。

你們可能會有疑問,爲何上面使用的兩個中間件並無看到調用next(),可是程序也能夠一直向下走呀?那是由於上面的兩個中間件是屬於內置和第三方中間件,在其封裝好的代碼中做者已經將next的調用寫了進去,中間件執行完已經調用了next(),只不過咱們做爲使用者看不到而已。下面經過一個咱們本身寫的中間件實現的簡易body-parser功能更清楚的瞭解next的使用。

手寫中間件,實現簡版body-parser

當咱們能夠熟練的使用第三方中間件的時候就要考慮如何本身寫一箇中間件。其實實現起來並不難,下面就是一個簡版的body-parser中間件的實現過程。
1.首先在項目中建立一個libs目錄,在目錄中建立一個body-parser.js文件。注意這裏咱們再也不須要安裝body-parser。

const querystring = require('querystring');

module.exports = {
  // 爲了模擬第三方中間件的調用方式,這裏也使用urlencoded包裹
  urlencoded() {
    return (req, res, next) => {
      let arr = [];
      req.on('data', buffer => {
        arr.push(buffer);
      });
      req.on('end', () => {
        let post = querystring.parse(Buffer.concat(arr).toString());
        // 講解析好的數據放到req對象的body屬性上
        req.body = post;
        // 調用next方法結束當前中間件的調用,執行後續的操做
        next();
      });
    };
  }
};

2.而後在server.js中引入咱們寫的中間件,這裏的body-parser就不是第三方的body-parser了,而是咱們本身寫的body-parser。

const express = require('express');
const body = require('./libs/body-parser');

let server = express();
server.listen(8080);

server.use(body.urlencoded());

server.post('/reg', (req, res, next) => {
  console.log(req.body);
  res.send('ok');
});

server.use(express.static('./'));

3.而後在項目根目錄建立user.html文件,內部實現一個簡單的form表單

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <form class="" action="http://localhost:8080/reg" method="post">
      <input type="text" name="user" value="">
      <input type="password" name="pass" value="">
      <input type="submit" name="" value="註冊">
    </form>
  </body>
</html>

4.最後啓動服務
node server.js
在瀏覽器中訪問 http://localhost:8080/user.html
填寫表單,點擊提交按鈕,查看在命令行中查看。
在這裏插入圖片描述
表單提交的數據成功被解析而且打印到命令行中了。

這樣一個最簡版的body-parser中間件就實現了,其實內部就是對post請求數據的解析處理。固然第三方的中間件裏面的邏輯處理要比咱們實現的複雜不少,不過原理都是同樣的。

底層原理(Connect框架)

其實express中間件的實現依賴了Connect中間件框架,也就是說早先版本的express框架的中間件徹底是由另外一個獨立的框架Connect實現的,Connect也是express框架的做者編寫的。在express3.0版本中是包含了Connect框架的。而4.0版本中已經移除了對Connect的依賴,在內部實現了Connect接口。

Connect框架的源碼寫的仍是很是經典的,next的設計尤其巧妙,簡單易懂。本篇只是對中間件的使用的介紹,而且還告訴你們如何本身寫中間件。若是對Connect的底層實現有興趣,請看下篇文章。《nodejs之中間件框架Connect源碼淺談》

相關文章
相關標籤/搜索