[英]node express: should you always call next() in a get or post handler?
到目前为止,我已经使用(req, res)
作为参数定义了我的get
和post
处理程序,假设我将这些处理程序放在中间件链中,并确保我在内部处理任何响应和错误处理这些处理程序......因此我没有提及next
并不重要。
这是一种有效且明智的方法,或者即使(目前)之后没有任何事情发生,也总是呼叫next()
是好的做法吗? 例如,也许在未来你可能想要在这些路线之后做一些处理......或者可能有一个原因我还没有遇到为什么总是调用next()
好习惯。
例如,快速路由指南中有以下简单示例:
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
响应处理程序而不是错误响应处理程序(为此似乎通常的做法是定义一个最终的错误处理程序并调用next(err)
)。 因此,在非错误情况下,您将调用next()
,在下面的中间件中,您将执行res.status(200).send(req.mydata)
,其中req.mydata
将添加到您的get
处理程序中。
不。如果您想要其他东西来处理请求,您应该只调用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
。
如果没有第二个处理程序,那么如果第一个调用next()
,则将使用标准404
处理程序。
如果将参数传递给next()
则将调用错误处理中间件。
我的经验法则是如果您要提供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);
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.