首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >错误:在通过对象数组进行映射和进行异步db调用时,无法在发送标头后设置它们。

错误:在通过对象数组进行映射和进行异步db调用时,无法在发送标头后设置它们。
EN

Stack Overflow用户
提问于 2020-08-07 02:07:17
回答 1查看 235关注 0票数 0

我在控制器中有一个用于post请求的函数,它将请求主体作为一个类似于以下内容的对象数组来接收:

代码语言:javascript
复制
[
    {
        "names": ["test company 1","test company 2"],
        "role": "electronics"
    },
     {
        "names": ["test company 3", "test company 4"],
        "role": "mechanical"
    }
]

在控制器函数中,我试图遍历它并更新许多文档及其角色,如下所示:

代码语言:javascript
复制
exports.setCompanyRoles= (req, res) => {
  req.body.map((data) => {
    Companies.updateMany({ name: { $in: data.names } }, { role: data.role })
      .then((result) => {
        res.status(200).json(result); //I know map is triggering this to be sent multiple times throwing error
      })
      .catch((err) => console.error(err));
  });
};

然后,代码正确地抱怨多次发送http报头:

代码语言:javascript
复制
Listening on port 3002
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:535:11)
    at ServerResponse.header (C:\teamSIO\server\node_modules\express\lib\response.js:771:10)
    at ServerResponse.send (C:\teamSIO\server\node_modules\express\lib\response.js:170:12)
    at ServerResponse.json (C:\teamSIO\server\node_modules\express\lib\response.js:267:15)
    at C:\teamSIO\server\controllers\adminConfigFlow.js:43:25
    at processTicksAndRejections (internal/process/task_queues.js:97:5) {
  code: 'ERR_HTTP_HEADERS_SENT'

我一直在想什么是最好的方法。由于异步调用,我无法在外部初始化结果变量,然后在map函数中更新它,然后使用它发送响应。但是,尽管有此错误,数据库仍然能够正确更新。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-07 02:20:08

听起来你已经知道你不能对同一个请求发送多个响应了。因此,相反,您需要收集所有的结果,然后发送一个响应。由于您有多个使用承诺的异步操作,所以您可以使用Promise.all()来知道它们什么时候完成,然后发送一个结果数组。

代码语言:javascript
复制
exports.setCompanyRoles= (req, res) => {
  Promise.all(req.body.map((data) => {
    return Companies.updateMany({ name: { $in: data.names } }, { role: data.role });
  })).then(results => {
       res.status(200).json(results);
  }).catch(err => {
       console.error(err);
       res.sendStatus(500);
  });
};

注意,我在数据库调用之前添加了一个return,这样您的req.body.map()就会产生一系列承诺。然后,您可以使用Promise.all()来了解所有这些承诺何时完成,并访问其所有已解析的值。

FYI,除了记录错误之外,我还添加了发送错误响应,因为您需要始终发送响应http请求,即使有错误。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63294197

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档