使用中介軟體和下一個回撥

Express 將 next 回撥傳遞給每個路由處理程式和中介軟體函式,這些函式可用於破壞跨多個處理程式的單個路由的邏輯。在沒有引數的情況下呼叫 next() 會告訴 express 繼續使用下一個匹配的中介軟體或路由處理程式。使用錯誤呼叫 next(err) 將觸發任何錯誤處理程式中介軟體。呼叫 next('route') 將繞過當前路由上的任何後續中介軟體並跳轉到下一個匹配路由。這允許將域邏輯分離為可重用的元件,這些元件是獨立的,更易於測試,更易於維護和更改。

多條匹配路線

/api/foo/api/bar 的請求將執行初始處理程式以查詢成員,然後將控制權傳遞給每個路由的實際處理程式。

app.get('/api', function(req, res, next) {
  // Both /api/foo and /api/bar will run this
  lookupMember(function(err, member) {
    if (err) return next(err);
    req.member = member;
    next();
  });
});

app.get('/api/foo', function(req, res, next) {
  // Only /api/foo will run this
  doSomethingWithMember(req.member);
});

app.get('/api/bar', function(req, res, next) {
  // Only /api/bar will run this
  doSomethingDifferentWithMember(req.member);
});

錯誤處理程式

錯誤處理程式是具有簽名 function(err, req, res, next) 的中介軟體。它們可以按路由設定(例如 app.get('/foo', function(err, req, res, next)),但通常,呈現錯誤頁面的單個錯誤處理程式就足夠了。

app.get('/foo', function(req, res, next) {
  doSomethingAsync(function(err, data) {
    if (err) return next(err);
    renderPage(data);
  });
});

// In the case that doSomethingAsync return an error, this special
// error handler middleware will be called with the error as the 
// first parameter.
app.use(function(err, req, res, next) {
  renderErrorPage(err);
});

中介軟體

上述每個函式實際上都是一箇中介軟體函式,只要請求與定義的路由匹配就會執行,但是可以在單個路由上定義任意數量的中介軟體函式。這允許在單獨的檔案和通用邏輯中定義中介軟體,以便在多個路由上重用。

app.get('/bananas', function(req, res, next) {
  getMember(function(err, member) {
    if (err) return next(err);
    // If there's no member, don't try to look
    // up data. Just go render the page now.
    if (!member) return next('route');
    // Otherwise, call the next middleware and fetch
    // the member's data.
    req.member = member;
    next();
  });
}, function(req, res, next) {
  getMemberData(req.member, function(err, data) {
    if (err) return next(err);
    // If this member has no data, don't bother
    // parsing it. Just go render the page now.
    if (!data) return next('route');
    // Otherwise, call the next middleware and parse
    // the member's data. THEN render the page.
    req.member.data = data;
    next();
  });
}, function(req, res, next) {
  req.member.parsedData = parseMemberData(req.member.data);
  next();
});

app.get('/bananas', function(req, res, next) {
  renderBananas(req.member);
});

在此示例中,每個中介軟體函式都可以位於其自己的檔案中,也可以位於檔案中其他位置的變數中,以便可以在其他路徑中重複使用。