Can't set headers after they are sent,几个客户端并发访问必现

2018-03-05 13:49:59 +08:00
 lupo
router.get('/', function (req, res, next) {
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('connect error');
throw err;
}
console.log('connect success');
db.collection('live_collection').find().toArray(function(err, result) {
if (err) {
console.log('find error');
db.close();
throw err;
}
console.log('query success');
db.close();
// console.log(result);
return res.json({message: 'request for live success', ret: 0, match: result});
})
})
});

return res.json({message: 'request for live success', ret: 0, match: result});这里出错,网上搜的说法和我这个都不一样,我这个用法很简单,应该不会存在 callback 被调用两次的情况。但据我抓包看,出错的时候服务会发送一个 404,这个应该是 express 自己发的,我的代码里面没有这样的逻辑。不知道为什么会有这样错误,折腾很久了也没找出原因,求大神帮助。。
5208 次点击
所在节点    Node.js
8 条回复
yimity
2018-03-05 14:52:29 +08:00
每个分支都 return 一下。
e8c47a0d
2018-03-07 16:22:14 +08:00
请注意 return 是写在回调里的,这个请求到最后都没有回复任何内容。另外用 async await 来简化代码把,还有 db 不需要每个请求都去连接,可以在 node 启动时连接,然后设置 global.db = db。

router.get('/', async (req, res) => {
try {
await db.collection('live_collection')
.find().toArray()
}
catch (e) {

}
res.json(...)
})
e8c47a0d
2018-03-07 16:24:48 +08:00
请求在 res.json 执行前已经被切断了
e8c47a0d
2018-03-07 16:28:34 +08:00
注意 MongoDB 如果写入操作失败不会 throw 错误,而是会返回一个 writeResult,需要自己 throw。
lupo
2018-03-08 14:02:01 +08:00
@e8c47a0d 谢谢大佬帮助,但这个问题不是必现的,只有在并发多的时候才出现,感觉不像是你说的那样。我是个 node.js 小白,感觉 node.js 比较轻量用来写一个 web API 服务,但这个问题一直没搞定。。。
从 console.log 的输出情况来看,出错的时候 mongodb 的接口并没有出错。。
e8c47a0d
2018-03-08 14:34:03 +08:00
很有可能是并发的时候,建立了太多 db 实例,到一定上限的时候被 mongo 驳回了……
lupo
2018-03-08 17:51:15 +08:00
@e8c47a0d 我的并发也不多,4~5 个客户端就出现了每个客户端 5 秒请求一次。。。实在不行,就换 python 或者 go 了
wotemelon
2018-03-12 09:00:31 +08:00
不需要每个请求都去 connect 一遍

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/434934

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX