我已经使用Node.js和Express.js创建了一个REST API。 在URL上,当我多次调用此URL时收到错误消息:
发送json错误:[错误:发送后无法设置标题。]
所以,我添加了一个try catch来捕获错误。但奇怪的是,这项工作很好。收到错误并发送我的回复:
try {
res.status(200).json(user);
} catch (e) {
console.log('send json error:',e);
}
res.on('finish', function() {
console.log('All is ok, response sent with user datas');
});
我认为这不是一个非常干净的解决方案。所以我想知道为什么会出现这个错误以及如何为这个问题编写一个干净的解决方案?
答案 0 :(得分:1)
所以从你的JSFiddle,我不得不说你可以用 lot 来模块化/清理你的代码。现在很难弄清楚发生了什么。虽然使用胖箭头表示法来实现闭包很方便,但是当你有很多顺序或并行的时候很难调试,因为它们完全是匿名的。
您也没有在任何地方指明其他中间件沿着该路由发射的内容,这可能也是多次响应尝试的来源。
所有这一切,第一个要做的事情非常简单:在每次调用res.send()
或res.end()
之前添加一个return语句。无论何时你打电话给其中一个,你都希望当前的功能停止做任何事情,所以要明确这一点,并且很多这类问题都会消失。
其次,为代码中的每个promise处理程序或回调添加命名函数。这至少可以为您提供更清晰的堆栈跟踪,并使您的代码对其他维护者更直观。
第三,考虑以符合名称的逻辑方式将这些功能分组到其他文件中。这将进一步说明您的堆栈跟踪(通过提供文件名和行号来查看)。
最后,虔诚地安装和使用node-inspector或类似的调试工具,设置断点并逐步执行代码。
//在OPs评论下面编辑
我不同意代码组织不是帖子的主要问题。这绝对是导致主要问题的原因。你的评论(真的应该在原始问题中)表明有问题的关闭是两次发射。该闭包是全局对象(坏主意)的事件处理程序,它在加载用户数据时触发事件,但是您将当前处理程序的范围推入其中(响应对象) ),这是您按照自己的方式组织代码时遇到的常见问题(范围出血)。
通过更好的模块化/结构,这些问题变得更加明显。你所暗示的是解决这个问题的黑客行为;真正的解决方案是更好地了解应用程序何时发生以及原因。
在这种情况下,请查看为何多次触发用户数据加载事件。我猜它不应该(至少不在同一个请求的范围内),但是如果它应该并且没关系,那么使用正确的promise链行为只处理一次(无论是第一次还是上次时间符合您的需求),只有在您准备好时才会调用res.json()
(并且只能调用一次)。