我在这里挠头,我使用bcrypt尝试登录用户,但我收到以下错误:
Error: Can't set headers after they are sent.
这是该路线的代码:
router.post('/login', (req, res, next) => {
User.find({ email: req.body.email })
.exec()
.then(user => {
if (user.length < 1) {
res.status(401).json({
message: 'Auth failed'
});
}
bcrypt.compare(req.body.password, user[0].password, (err, result) => {
if (err) {
res.status(401).json({
message: 'Auth failed'
});
}
if (result) {
res.json(200).json({
message: 'Auth successful'
});
}
return res.status(401).json({
message: 'Auth failed 3'
});
});
})
.catch(err => {
res.status(500).json({
error: err
});
});
});
我认为错误可能来自if else
语句,并尝试两次发送标题,但是我会在继续下一个条件号之前结束它们?我想念一下这里的东西吗?
答案 0 :(得分:1)
当您的代码尝试为同一请求发送多个响应时,会看到您看到的错误。此错误的典型原因是您处理异步操作的编码错误。在您显示的代码中,我可以看到以下可能导致此错误的错误:
如果user.length < 1
,则执行res.status(401).json(...)
,然后让代码继续运行,然后发送其他回复。
如果您从bcrypt.compare()
收到错误,则会发送错误响应,然后让代码继续运行并发送其他回复。
如果bcrypt.compare()
成功,则发送res.json(200).json(...),这是错误的。你可能意味着res.status(200).json(...)
。
如果bcrypt.compare()
成功并且您有result
,则会发送两个回复。
在查看代码时,您似乎认为只要执行res.json()
函数返回并且没有执行其他代码。事实并非如此。在你点击return
之前,该函数中的其余代码将继续执行。
以下是修复它的一种方法(添加一些return
语句和一个else
):
router.post('/login', (req, res, next) => {
User.find({ email: req.body.email }).exec().then(user => {
if (user.length < 1) {
res.status(401).json({message: 'Auth failed'});
return;
}
bcrypt.compare(req.body.password, user[0].password, (err, result) => {
if (err) {
res.status(401).json({message: 'Auth failed'});
return;
}
if (result) {
res.json({message: 'Auth successful'});
} else {
res.status(401).json({message: 'Auth failed 3'});
}
});
}).catch(err => {
res.status(500).json({error: err});
});
});
或者,为了以更清洁的方式执行此操作,其中所有具有相同状态的响应被组合并且所有流控制都使用promises完成,您可以执行以下操作:
const util = require('util');
bcyrpt.compareAsync = util.promisify(bcrypt.compare);
router.post('/login', (req, res, next) => {
User.find({ email: req.body.email }).exec().then(user => {
if (user.length < 1) {
throw new Error('No user match');
}
return bcrypt.compareAsync(req.body.password, user[0].password).then(result =>
if (!result) {
throw new Error('Auth failed 2');
}
res.json({message: 'Auth successful'});
}
}).catch(err => {
res.json(401).json({message: err.message});
});
}).catch(err => {
res.status(500).json({error: err});
});
});