Express.js:已在REST API上发送的标头

我用Node.js和Express.js创build了一个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'); }); 

我认为这不是很干净的解决scheme。 所以我想知道为什么这个错误是抛出,我怎么能为这个问题写一个干净的解决scheme?

所以从你的JSFiddle,我不得不说,你可以做很多模块化/清理你的代码。 现在要弄清楚在哪里发生了什么非常困难。 虽然使用箭头符号来表示闭包是很方便的,但是当你有很多顺序或并行的debugging时,真的很难debugging,因为它们是完全匿名的。

你也不能指出其他中间件沿着这条路线发射什么东西,这可能是多个响应尝试的来源。

总之, 首先要做的事情非常简单:在每次调用res.send()res.end()之前添加一条return语句。 任何时候你打电话给其中一个人,你都希望你现在的职能停止任何事情,所以要明确这一点,这类问题就会消失。

其次,为代码中的每个承诺处理程序或callback添加命名函数。 这至less会给你更清晰的堆栈跟踪,让你的代码对其他维护者更直观。

第三,考虑将这些函数以逻辑方式分组到其他文件中,您可以通过名称来请求这些函数。 这将进一步照亮你的堆栈跟踪(通过给你的文件名和行号看看)。

最后,虔诚地安装和使用node-inspector或类似的debugging工具,设置断点并逐步执行代码。

//在下面的OP注释之后进行编辑

我不同意代码组织不是这个职位的主要问题。 这绝对是导致主要问题。 您的评论(原本应该在原来的问题中)表明有问题的closures是两次发射。 这个闭包是一个全局对象(坏主意)的事件处理程序,当用户数据被加载时触发一个事件,但是你把当前处理程序的范围向下(响应对象),这是一个常见的问题当你按照你的方式组织代码时,你会遇到(范围stream血)。

通过更好的模块化/结构,这些问题更加迅速地变得更加明显。 你提出的build议是解决问题的方法。 真正的解决scheme是更好地理解什么时候发生在你的应用程序中,为什么。

在这种情况下,看看为什么用户数据加载事件不止一次触发。 我猜它不应该(至less不在同一个请求的范围内),但是如果它应该是这样,那么使用正确的承诺链行为来处理它只有一次(不pipe这是第一次还是最后一次取决于你的需要),只有当你真的准备好(并且只有一次)时才调用res.json() )。