到目前为止,我已经使用get
作为参数定义了我的post
和(req, res)
处理程序,并假设我将这些处理程序放在中间件链中,并且make确保我在这些处理程序中正确处理任何响应和错误处理......因此,我没有对next
进行任何引用并不重要。
这是一种有效且明智的做法,或者即使(目前)之后什么都没有发生,也总是致电next()
是好的做法?例如,也许将来您可能希望在这些路线之后进行一些处理......或者可能还有一个原因我还没有遇到为什么总是拨打next()
这是一个好习惯。
例如,快递routing guide中有以下简单示例:
app.get('/example/b', function (req, res, next) {
console.log('the response will be sent by the next function ...')
next()
}, function (req, res) {
res.send('Hello from B!')
})
当然,我很欣赏这是一个非常简单的例子来说明处理程序可以链接,并不打算为get
处理程序提供完整的框架,但定义和使用会更好next
甚至在第二个处理程序中,如下所示?
app.get('/example/b', function (req, res, next) {
console.log('the response will be sent by the next function ...')
next()
}, function (req, res, next) {
res.send('Hello from B!')
next()
})
或者实际上通常的做法是假设将响应发送回客户端的处理函数不调用next()
...即假设链条将是在实际发送响应的处理程序结束?
或者在这一点上没有既定的做法?
我甚至想知道在get
处理程序中发送任何响应是否常见但是将其推迟到后面的专用响应处理程序...我的意思是OK
响应处理程序而不是错误响应处理程序(通常的做法是定义final error handler并调用next(err)
)。因此,在非错误情况下,您可以致电next()
,在以下中间件中,您可以执行res.status(200).send(req.mydata)
,req.mydata
处理程序中添加了get
。
答案 0 :(得分:5)
没有。如果您想要其他人来处理请求,您应该只调用next()
。通常它就像是说你的路线可能符合这个要求,但你想表现得像它没有做的那样。例如,您可能有两个处理程序用于相同的路径:
app.get('/test', (req, res, next) => {
if (something) {
return next();
}
// handle request one way (1)
});
app.get('/test', (req, res) => {
// handle request other way (2)
});
总是调用第一个匹配的处理程序,因此对于GET /test
请求,将调用第一个处理程序,但是它可以选择将控件传递给第二个处理程序,就好像第一个处理程序没有匹配请求。
请注意,如果第二个处理程序并不打算将请求传递给下一个处理程序,那么它的参数中甚至不会有next
。
如果没有第二个处理程序,那么如果第一个处理程序名为404
,则将使用标准next()
处理程序。
如果将参数传递给next()
,则会调用错误处理中间件。
答案 1 :(得分:1)
我的经验法则是,如果您要提供20x(成功)响应代码,则处理处理程序中的响应,如果不是,则处理集中式错误处理。在实践中看起来像这样:
// ./routes/things.js
const express = require('express');
const Thing = require('../models/thing');
const Router = express.Router();
// note, the handlers might get pulled out into a controllers file, if they're getting more complex.
router.param('thingId', (req, res, next, id) => {
Thing.findById(id, (e, thing) => {
if (e) return next(e);
// let's say we have defined a NotFoundError that has 'statusCode' property which equals 404
if (!bot) return next(new NotFoundError(`Thing ${id} not found`));
req.thing = thing;
return next();
});
});
router.get('/', (req, res, next) => {
// possibly pull in some sort, limit, and filter stuff
Thing.find({}, (e, things) => {
if (e) return next(e);
res.send(things);
});
});
router.route('/:thingId')
.get((req, res) => {
// if you get here, you've already got a thing from the param fn
return res.send(req.thing);
})
.put((req, res, next) => {
const { name, description } = req.body; // pull whitelist of changes from body
let thing = req.thing;
thing = Object.assign(thing, { name, description }); // copy new stuff into the old thing
thing.save((e) => {
if (e) return next(e);
return res.send(thing); // return updated thing
});
});
将每个逻辑块保留在自己的文件中可以减少重复
// ./routes/index.js then mounts the subrouters to the main router
const thingsRoute = require('./things');
const express = require('express');
const router = express.Router();
/* .... other routes **/
router.use('/things', thingsRoute);
然后集中处理错误,可以将其安装在自己的文件中,也可以安装在应用程序上:
// in ./index.js (main app entry point)
const express = require('express');
// this will require by default ./routes/index.js
const routes = require('./routes');
const app = express();
const log = require('./log');// I prefer debug.js to console.log, and ./log.js is my default config file for it
/* ... other app setup stuff */
app.use(routes);
// you can mount several of these, passing next(e) if you don't handle the error and want the next error handler to do so.
app.use((err, req, res, next) => {
// you can tune log verbosity, this is just an example
if (err.statusCode === 404) {
return res.status(404).send(err.message);
}
log.error(err.message);
log.verbose(err.stack); // don't do stack traces unless log levels are set to verbose
return res.status(500).send(err.message);
});