V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lupo
V2EX  ›  Node.js

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

  •  
  •   lupo · 2018-03-05 13:49:59 +08:00 · 5214 次点击
    这是一个创建于 2491 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 自己发的,我的代码里面没有这样的逻辑。不知道为什么会有这样错误,折腾很久了也没找出原因,求大神帮助。。
    8 条回复    2018-03-12 09:00:31 +08:00
    yimity
        1
    yimity  
       2018-03-05 14:52:29 +08:00 via Android
    每个分支都 return 一下。
    e8c47a0d
        2
    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
        3
    e8c47a0d  
       2018-03-07 16:24:48 +08:00
    请求在 res.json 执行前已经被切断了
    e8c47a0d
        4
    e8c47a0d  
       2018-03-07 16:28:34 +08:00
    注意 MongoDB 如果写入操作失败不会 throw 错误,而是会返回一个 writeResult,需要自己 throw。
    lupo
        5
    lupo  
    OP
       2018-03-08 14:02:01 +08:00
    @e8c47a0d 谢谢大佬帮助,但这个问题不是必现的,只有在并发多的时候才出现,感觉不像是你说的那样。我是个 node.js 小白,感觉 node.js 比较轻量用来写一个 web API 服务,但这个问题一直没搞定。。。
    从 console.log 的输出情况来看,出错的时候 mongodb 的接口并没有出错。。
    e8c47a0d
        6
    e8c47a0d  
       2018-03-08 14:34:03 +08:00
    很有可能是并发的时候,建立了太多 db 实例,到一定上限的时候被 mongo 驳回了……
    lupo
        7
    lupo  
    OP
       2018-03-08 17:51:15 +08:00
    @e8c47a0d 我的并发也不多,4~5 个客户端就出现了每个客户端 5 秒请求一次。。。实在不行,就换 python 或者 go 了
    wotemelon
        8
    wotemelon  
       2018-03-12 09:00:31 +08:00
    不需要每个请求都去 connect 一遍
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   902 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 20:01 · PVG 04:01 · LAX 12:01 · JFK 15:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.