【问题标题】:Returning a response immediately with res.json使用 res.json 立即返回响应
【发布时间】:2015-02-17 00:45:42
【问题描述】:

我有一个快速路由,它接受一些参数,查询数据库,然后返回一些响应。

我正在使用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

似乎最后一行总是运行,即使它找到了一个用户(它应该将数据返回给客户端并完成)。

为什么res.json(..)找到用户后不立即返回客户端?由于已经设置了标题,所以当最后一行运行时,它会抛出该错误。

【问题讨论】:

    标签: javascript node.js express sequelize.js


    【解决方案1】:

    您只需要有条件地返回一个错误。行:

    res.status(500).json({"error":"Something went wrong. Check your input."});
    

    总是被执行。这样做的原因是您传递给 find 方法的函数仅在 db 响应后的事件循环中稍后调用。这意味着当调用该回调时,您已经在响应中设置了错误。

    您应该删除该行或决定何时返回错误但不要每次都返回错误。

    【讨论】:

    • 如果我忘记处理某些条件,返回一些默认响应的好方法是什么?
    • 由于 node.js 是基于回调的任何长时间运行的任务,你不能像在 Java 中那样简单地将所有内容放在一个大的 try catch 块中。您已经在 catch 回调中返回了一个错误。如果 find 调用中出现任何问题,这将是响应。我认为你已经在做你需要做的一切。只需删除该行。
    【解决方案2】:

    记住 javascript 是异步的。

    只要你调用这个函数

    models.user.find({ where: { name: name }})
    

    最后一行被执行:

    res.status(500).json({"error":"Something went wrong. Check your input."});
    

    您似乎正在尝试满足两种情况:

    1. 来自客户端的错误请求数据 - 即没有给出 gid
    2. 内部服务器错误 - 即数据库错误

    我建议将您的 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 状态代码列表:

    http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

    【讨论】:

      【解决方案3】:

      @bhspencer 说的是对的。您必须删除最后一行。

      该行可能会在数据库中的任何查询之前执行。

      【讨论】:

        【解决方案4】:

        你需要在里面实现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代码执行的处理。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-14
          • 1970-01-01
          • 1970-01-01
          • 2018-03-25
          • 1970-01-01
          相关资源
          最近更新 更多