使用中间件和下一个回调
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);
});
在此示例中,每个中间件函数都可以位于其自己的文件中,也可以位于文件中其他位置的变量中,以便可以在其他路径中重复使用。