使用 res.json 立即返回响应
Returning a response immediately with res.json
我有一个快速路由,它接受一些参数,查询数据库,然后 return 一些响应。
我正在使用 sequelize 查询数据库:
router.get('/query', function(req,res) {
var name = req.params.name;
var gid = req.params.gid;
// Query the db
models.user.find({ where: { name: name }}).then(function(user) {
models.group.find({ where: { id: gid }}).then(function(group) {
// if user found, return data to client
if (user) {
res.json({"user": user, "group": group});
}
});
}).catch(function(error) {
// catch any errors from db query
res.status(500).json({"error":error});
});
// Return a server error for any other reason
// This causes ERROR
res.status(500).json({"error":"Something went wrong. Check your input."});
});
但我在最后一行不断收到错误消息:
Can't set headers after they are sent
似乎最后一行总是 运行,即使它找到了用户(应该 return 向客户端发送数据并完成)。
为什么在找到用户后 res.json(..)
不立即 return 给客户端?由于 headers 已经设置,当最后一行 运行 时,它会抛出该错误。
您只需要有条件地 return 一个错误。该行:
res.status(500).json({"error":"Something went wrong. Check your input."});
总是被执行。这样做的原因是你传递给 find 方法的函数只会在数据库响应后在事件循环中调用。这意味着当调用该回调时,您已经在响应中设置了错误。
您应该删除该行或决定何时 return 出错但不要每次都 return 出错。
您需要在
中实现一个return
models.user.find({ where: { name: name }}).then(function(user) {
models.group.find({ where: { id: gid }}).then(function(group) {
// if user found, return data to client
if (user) {
res.json({"user": user, "group": group});
return;
}
});
}).catch(function(error) {
// catch any errors from db query
res.status(500).json({"error":error});
return;
});
实际上res.json(
没有return
语句就没有结束node.js代码执行的处理。
记住 javascript 是异步的。
只要你调用这个函数
models.user.find({ where: { name: name }})
最后一行被执行:
res.status(500).json({"error":"Something went wrong. Check your input."});
您似乎在尝试满足两种情况:
- 来自客户端的错误请求数据 - 即没有给出 gid
- 内部服务器错误 - 即数据库错误
我建议将您的 catch 函数更改为如下所示:
.catch(function(error) {
// catch any errors from db query
if (err === "Unable to connect to database") {
return res.status(500).json({ error: "There was an internal error"})
}
res.status(400).json({"error": "Bad input, please ensure you sent all required data" });
});
阅读标准 HTTP 状态代码列表:
@bhspencer 说的对。您必须删除最后一行。
该行可能在数据库中的任何查询之前执行。
我有一个快速路由,它接受一些参数,查询数据库,然后 return 一些响应。
我正在使用 sequelize 查询数据库:
router.get('/query', function(req,res) {
var name = req.params.name;
var gid = req.params.gid;
// Query the db
models.user.find({ where: { name: name }}).then(function(user) {
models.group.find({ where: { id: gid }}).then(function(group) {
// if user found, return data to client
if (user) {
res.json({"user": user, "group": group});
}
});
}).catch(function(error) {
// catch any errors from db query
res.status(500).json({"error":error});
});
// Return a server error for any other reason
// This causes ERROR
res.status(500).json({"error":"Something went wrong. Check your input."});
});
但我在最后一行不断收到错误消息:
Can't set headers after they are sent
似乎最后一行总是 运行,即使它找到了用户(应该 return 向客户端发送数据并完成)。
为什么在找到用户后 res.json(..)
不立即 return 给客户端?由于 headers 已经设置,当最后一行 运行 时,它会抛出该错误。
您只需要有条件地 return 一个错误。该行:
res.status(500).json({"error":"Something went wrong. Check your input."});
总是被执行。这样做的原因是你传递给 find 方法的函数只会在数据库响应后在事件循环中调用。这意味着当调用该回调时,您已经在响应中设置了错误。
您应该删除该行或决定何时 return 出错但不要每次都 return 出错。
您需要在
中实现一个return
models.user.find({ where: { name: name }}).then(function(user) {
models.group.find({ where: { id: gid }}).then(function(group) {
// if user found, return data to client
if (user) {
res.json({"user": user, "group": group});
return;
}
});
}).catch(function(error) {
// catch any errors from db query
res.status(500).json({"error":error});
return;
});
实际上res.json(
没有return
语句就没有结束node.js代码执行的处理。
记住 javascript 是异步的。
只要你调用这个函数
models.user.find({ where: { name: name }})
最后一行被执行:
res.status(500).json({"error":"Something went wrong. Check your input."});
您似乎在尝试满足两种情况:
- 来自客户端的错误请求数据 - 即没有给出 gid
- 内部服务器错误 - 即数据库错误
我建议将您的 catch 函数更改为如下所示:
.catch(function(error) {
// catch any errors from db query
if (err === "Unable to connect to database") {
return res.status(500).json({ error: "There was an internal error"})
}
res.status(400).json({"error": "Bad input, please ensure you sent all required data" });
});
阅读标准 HTTP 状态代码列表:
@bhspencer 说的对。您必须删除最后一行。
该行可能在数据库中的任何查询之前执行。