【问题标题】:"Cannot set headers after they are sent to the client" error after post request发布请求后出现“发送到客户端后无法设置标题”错误
【发布时间】:2021-03-15 22:24:23
【问题描述】:

需要帮助解决一些奇怪的错误

这是托管在heroku上的express,nodejs服务

这是我的路由控制器代码

async function PopupConroller(req, res) {


        let credential = req.credential;
        let zoho_token = null;
        console.log('res :>> ', res);
        try {
            zoho_token  = await axios.post(`https://accounts.zoho.com/oauth/v2/token?client_id=${credential.client_id}&client_secret=${credential.client_secret}&refresh_token=${credential.refresh_token}&grant_type=refresh_token`);
            console.log('zoho_token.data :>> ', zoho_token.data);

        } catch (error) {
            console.log('ex 2 :>> ',error);
        }
        console.log('res :>> ', res);


       res.status(200).json({status:"ok"});

       return;

}

当服务收到请求时,代码抛出此错误 (axios.post 请求没有错误)

回复:200 OK with no body

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
 at ServerResponse.setHeader (_http_outgoing.js:530:11)
 at ServerResponse.header (/app/node_modules/express/lib/response.js:771:10)
 at ServerResponse.json (/app/node_modules/express/lib/response.js:264:10)
 at PopupConroller (/app/voicenter.js:261:28)
 at processTicksAndRejections (internal/process/task_queues.js:97:5)

删除这些行时一切正常 响应:200 OK,{status:"ok"}

async function PopupConroller(req, res) {


        let credential = req.credential;
        let zoho_token = null;
        console.log('res1 :>> ', res);
        try {
            //zoho_token  = await axios.post(`https://accounts.zoho.com/oauth/v2/token?client_id=${credential.client_id}&client_secret=${credential.client_secret}&refresh_token=${credential.refresh_token}&grant_type=refresh_token`);
            //console.log('zoho_token.data :>> ', zoho_token.data);

        } catch (error) {
            console.log('ex 2 :>> ',error);
        }
        console.log('res2 :>> ', res);


       res.status(200).json({status:"ok"});

       return;

}

在第一个例子中,
当我检查 res 对象(console.log res1)时,没有发送标头,但在第二个(console.log res2)中,我注意到响应标头发回了。

这条线发送标题的方式? *需要说明其他路线中的类似代码可以正常工作

zoho_token  = await axios.post(`https://accounts.zoho.com/oauth/v2/token?client_id=${credential.client_id}&client_secret=${credential.client_secret}&refresh_token=${credential.refresh_token}&grant_type=refresh_token`);

感谢您的帮助... 谢谢

【问题讨论】:

  • 我理解错误,但我不明白你想说什么。你能改写你的问题吗?
  • 您的 /app/voiceenter.js 文件中的第 261 行到底是什么?另外,您是否在 express 中设置了可能启动的错误处理程序?当您收到此错误时,这意味着一些响应已发送回客户端,因此客户端是否收到任何数据?
  • 错误来自中间件之一,有 res.end() 之后没有返回,通过在解决错误后添加 return 语句。但我仍然不确定这条路线是否有错误,因为我在几条路线上使用了相同的中间件。不过感谢您的回复。
  • @TalWeizman 您能否扩展上述评论?我不清楚这里的真正问题。 PopupController 是一个承诺,应该 resolve 带有一个令牌。您将以状态码 200 和 json 对象结束响应,而实际上此函数是您应该在 调用它的任何处理程序中使用的承诺。你能分享打电话给PopupControllerhandler吗?你应该在那里结束响应,而不是在你的承诺中......

标签: javascript node.js express


【解决方案1】:

我只是在猜测,这是你想要的吗?

要扩展下面的 sn-p 代码,您会收到错误 cannot set headers after they are sent to the client,因为 axios.post() 正在发出 HTTP 发布请求。

在您的代码中,您通过 axios 进行 HTTP 调用,以便发送标头。

之后,JS 解析器继续评估代码并在 try 块之后,因为没有错误,它评估 res.status() 以获取已发送的响应,因此出现错误。

因此,要解决此问题,您可以像处理帖子一样处理发布请求,无需再次将响应重新发送给客户端。然后,您可以使用“thenable”函数中的承诺响应“做某事”。

如果你想通过 axios 发布一个可选对象,你可以通过将参数传递给发布请求来做到这一点。

async function PopupConroller(req, res) {

        let credential = req.credential;
        let zoho_token = await axios.post("whatever", {"cat": "meaows"})
        .then((response)=> {
            // do something with the response
        })
        .catch((err) => console.log(err))
  
}

【讨论】:

  • 有什么区别?
  • 这是一个反问的问题吗?
  • 似乎我的评论有效,因为您在我写完之后添加了解释它的详细信息;)
  • 是的,我意识到用户需要对错误进行解释,所以我添加了它。谢谢
  • 错误来自中间件之一,有 res.end() 之后没有返回,通过在解决错误后添加 return 语句。但我仍然不确定这条路线是否有错误,因为我在几条路线上使用了相同的中间件。不过感谢您的回复。
猜你喜欢
  • 2021-02-17
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
  • 2017-05-31
  • 2019-07-17
  • 2022-01-13
  • 2021-03-30
相关资源
最近更新 更多