![](/img/trans.png)
[英]Node.js Express.js Mongoose Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
[英]Using express.js I get this error: Uncaught Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
我想就这个问题寻求帮助。 这段代码的目标是:
artist
使用从信息指定的艺术家ID artist
请求主体的属性,并将其保存到数据库中。 在响应主体的artist
属性上返回带有更新艺术家的 200 响应artist
ID 的artist
不存在,则返回 404 响应。这是失败的路线:
artistsRouter.put('/:artistId', (req, res, next) => {
if(areParamsRight(req.body.artist)){ // areParamsRight checks for the correct types and body's fields
db.serialize(() => {
db.run('UPDATE Artist SET name = $name, date_of_birth = $date_of_birth, biography = $biography WHERE id = $iD',
{ $name: req.body.artist.name,
$date_of_birth: req.body.artist.dateOfBirth,
$biography: req.body.artist.biography,
$is_currently_employed: req.body.artist.isCurrentlyEmployed,
$iD: req.artist.id }, (error) => { if(error) { next(error) }
});
db.get(`SELECT * FROM Artist WHERE id = $thisId `, { $thisId: req.artist.id } , (err, artist) => {
if(err){
next(err);
} else {
res.status(200).send(artist);
console.log('response sent. ')
}
})
})
} else {
res.setStatus(400);
}
});
我尝试了以下方法:
artistsRouter.put('/:artistId', (req, res, next) => {
if(areParamsRight(req.body.artist)){
db.serialize(() => {
db.run('UPDATE Artist SET name = $name, date_of_birth = $date_of_birth, biography = $biography WHERE id = $iD',
{ $name: req.body.artist.name,
$date_of_birth: req.body.artist.dateOfBirth,
$biography: req.body.artist.biography,
$is_currently_employed: req.body.artist.isCurrentlyEmployed,
$iD: req.artist.id }, (error) => { if(error) { next(error) }
});
next();
})
} else {
res.setStatus(400);
}
});
artistsRouter.put('/:artistId', (req, res, next) => {
db.get(`SELECT * FROM Artist WHERE id = $thisId `, { $thisId: req.artist.id } , (err, artist) => {
if(err){
next(err);
} else {
res.status(200).send(artist);
console.log('response sent. ')
}
})
})
在辅助函数下面。 它似乎工作正常,因为它也用于 POST 路由。
// this function will accept req object and will return true if params are the proper type.
function areParamsRight(obj) {
const name = obj.name, dateOfBirth = obj.dateOfBirth, biography = obj.biography;
if( Object.keys(obj).includes('name' && 'dateOfBirth' && 'biography')
&& typeof name === 'string' && typeof dateOfBirth === 'string' && typeof biography === 'string' ){
return true;
} else return false;
}
module.exports = areParamsRight;
先感谢您。
当数据库调用出现错误时,这段代码会导致发送两个响应:
db.run('UPDATE Artist SET name = $name, date_of_birth = $date_of_birth, biography = $biography WHERE id = $iD',
{ $name: req.body.artist.name,
$date_of_birth: req.body.artist.dateOfBirth,
$biography: req.body.artist.biography,
$is_currently_employed: req.body.artist.isCurrentlyEmployed,
$iD: req.artist.id }, (error) => { if(error) { next(error) }
});
next();
如果您以一种使代码流更清晰的方式对其进行格式化,如下所示:
artistsRouter.put('/:artistId', (req, res, next) => {
if (areParamsRight(req.body.artist)) {
db.serialize(() => {
db.run('UPDATE Artist SET name = $name, date_of_birth = $date_of_birth, biography = $biography WHERE id = $iD', {
$name: req.body.artist.name,
$date_of_birth: req.body.artist.dateOfBirth,
$biography: req.body.artist.biography,
$is_currently_employed: req.body.artist.isCurrentlyEmployed,
$iD: req.artist.id
}, (error) => {
if (error) {
next(error)
}
});
next();
})
} else {
res.setStatus(400);
}
});
可以看到,只要areParamsRight()
返回 true,那么代码就会一直执行db.run()
然后调用next()
。 但是,如果db.run()
有错误,那么代码也会调用next(error)
。 但是由于这将被异步调用,对next()
的调用已经执行,这将尝试向同一请求发送第二个响应,因此可能会生成您看到的错误类型(尝试向同一个请求发送两个响应)要求)。
在这里想要的行为是什么有点令人困惑。 首先,您只想发送一个响应,而不是两个。 但是,由于这是一个.put()
请求处理程序而不是中间件处理程序,因此您似乎应该在这里发送响应而不是调用next()
。 我认为应该是这样的:
artistsRouter.put('/:artistId', (req, res, next) => {
if (areParamsRight(req.body.artist)) {
db.serialize(() => {
db.run('UPDATE Artist SET name = $name, date_of_birth = $date_of_birth, biography = $biography WHERE id = $iD', {
$name: req.body.artist.name,
$date_of_birth: req.body.artist.dateOfBirth,
$biography: req.body.artist.biography,
$is_currently_employed: req.body.artist.isCurrentlyEmployed,
$iD: req.artist.id
}, (error) => {
if (error) {
next(error); // report error
} else {
res.sendStatus(200); // report success
}
});
})
} else {
res.sendStatus(400);
}
});
另请注意,您最后有res.setStatus(400)
,我认为您的意思是res.sendStatus(400)
。
注意:由于您在此路由处理程序中只运行一个数据库查询,因此您似乎不需要在db.serialize()
包装东西。 但是,我不是 SQL 专家。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.