Express的使用筆記3 中介軟體

JocelynFung發表於2024-10-12





日誌中介軟體

// 掛載會每個介面都執行這段程式碼
app.use((req,res,next)=>{
    console.log(req.method,req.url,Date.now())
    next() //下一個中介軟體
})

2.中介軟體的順序很重要
如果有一個普通介面寫在上面程式碼之前,那麼就不會進入上面的函式中
但是如果在介面中第二個回撥函式的引數中加入next,則可以進入

// 不會列印時間戳及相關資訊
app.get("/todos", async (req, res) => {
  try {
    const db = await getDB();
    res.status(200).json(db.todos);
  } catch (err) {
    return res.status(500).json({ error: err.message });
  }
});
// 可以列印了~
app.get("/todos", async (req, res, next) => {
  try {
    const db = await getDB();
    res.status(200).json(db.todos);
    next()
  } catch (err) {
    return res.status(500).json({ error: err.message });
  }
});

我是講武德的,這些課件截圖源於b站up主小打小鬧Studio
https://space.bilibili.com/13625996


在中介軟體函式中可以執行以下任何任務:
1).執行任何程式碼
2).修改request或response響應物件
3).結束請求響應週期
4).呼叫下一個中介軟體
如果當前的中介軟體功能沒有結束請求-響應週期,則必須使用next()將控制權傳遞給下一個中介軟體功能。否則,該請求將被掛起。

2.Express中介軟體分類:
1)應用程式級別中介軟體 express例項.xxx
2)路由級別中介軟體 express.Router()
3)錯誤處理中介軟體 和其他中介軟體函式一樣,但是四個引數
4)內建中介軟體
5)第三方中介軟體

1)透過Express例項掛載的中介軟體
a)不做任何限定的中介軟體

app.use((req, res, next) => {
  console.log(req.method, req.url, Date.now());
  next(); //下一個中介軟體
});

b)限定請求方法+請求路徑的中介軟體
就是符合條件的APi被呼叫後才會進入這個中介軟體

//限定請求路徑
app.use('/task',(req, res, next) => {
  console.log(req.method, req.url, Date.now());
  next(); //下一個中介軟體
});

app.get('/task',(req, res, next) => {
 res.status(200).send('是否會進入?')
})
//----頁面進入/task中介軟體去列印方法和時間戳也會有‘是否進入’

//限定請求路徑
app.use('/aaa',(req, res, next) => {
  console.log(req.method, req.url, Date.now());
  next(); //下一個中介軟體
});
//---這種就是不會進入列印了,因為匹配不上了

c)多個處理函式

app.use(
  "/",
  (req, res, next) => {
    console.log(req.method, req.url, Date.now());
    next();
  },
  (req, res, next) => {
    console.log('也會進來嗎');
    // next();  //如果註釋掉就不會進入下面的介面了
  }
);

app.get("/", (req, res, next) => {
  res.status(200).send("是否會進入?");
});

d)next('route') 下一步進入請求,而不是普通下一步

app.get(
  "/user/:id",
  function (req, res, next) {
    console.log(req.method, req.url, Date.now());
    console.log(typeof(req.params.id),'999')
    if (req.params.id === '2') {
      next("route"); //跳過也會進來嗎函式的執行,直接進入是否會進入
    } else {
      next(); //繼續往下執行
    }
  },
  function (req, res, next) {
    console.log("也會進來嗎");
    next();
  }
);

app.get("/user/:id", (req, res, next) => {
  res.status(200).send("是否會進入?");
});

2)路由級別中介軟體
每個請求都需要app.xxx太過於繁瑣 ,可以使用路由例項 相當於mini express 例項
後續就透過router.xxx()
a)根目錄下建立一個router.js 檔案,建立一個router例項

const express = require('express')
const router = express.Router()

b)配置路由

router.get('/',(req,res,next)=>{})

c) 匯出路由例項

module.exports = router

d)將路由整合/掛載到Express例項應用中

const router = require('./router);
app.use(router)
//app.use('/abc',router) //在所有的路由前面都叫上限定訪問的字首

//可以將在app.js中寫的所有路由配置放到router.js去

3)錯誤處理中介軟體
與其他中介軟體函式相同的方式定義錯誤處理中介軟體函式,除了使用四個引數而不是三個引數,一定是四個引數
一般在所有的中介軟體之後掛載錯誤處理函式中間

app.use((err,req,res,next)=>{
  console.log(err.stack)
  res.status(500).json({error:err.message})
})

在try catch中的catch裡面使用next(err),傳遞錯誤的資訊,跳過所有剩餘的非錯誤處理路由和中介軟體函式,其實就是報錯之後去觸發錯誤處理函式,然後就結束任務
在router.js中將前面的所有路由中介軟體的catch裡面都修改成next(err)

router.post("/todos", async (req, res,next) => {
  try {
    const db = await getDB();
    const reqBd = req.body;
    if (!reqBd.title) {
      return res.status(422).send({ error: "The field title is required" });
    }
    const lastTodoItem = db.todos[db.todos.length - 1];
    db.todos.push({
      id: lastTodoItem ? lastTodoItem.id + 1 : 1,
      title: reqBd.title,
    });
    await saveDB(db);
    res.status(200).send("新增成功!");
  } catch (err) {
    next(err);
  }
});

模擬一下報錯的場景,正常可以響應500與對應的錯誤資訊

通常我們會在最後的位置放置一個404的處理中介軟體函式,其實出現404的時候也有一個預設的html提示樣式介面
404 與500型別的中介軟體沒有先後的影響,會對應觸發,但是其餘會依此從上往下執行

app.use((req,res,next)=>{
  res.status(404).send('404 not found)
})

4)內建中介軟體
express.json() ---application/json
express.urlencoded() ---application/x-www-form-urlcoded
express.raw() ---application/octet-stream
express.text() ---text/plain
express.static() ---託管靜態資原始檔
5)第三方中介軟體
為了極簡靈活的特性,epxress4之後將很多的中介軟體進行獨立 ----middleware module
看文件使用即可
https://expressjs.com/zh-cn/resources/middleware.html

demo使用這些第三方中介軟體~~ 日誌輸出中介軟體
a)裝包 npm install morgan
b)引入 var morgan = require('morgan')
c)掛載 app.use(morgan('tiny'))

相關文章