Ошибка: невозможно установить заголовки после их отправки при сопоставлении через массив объектов и выполнении вызовов asyn c db - PullRequest
0 голосов
/ 07 августа 2020

У меня есть функция в контроллере для почтового запроса, которая получает тело запроса в виде массива объектов, которые выглядят следующим образом:

[
    {
        "names": ["test company 1","test company 2"],
        "role": "electronics"
    },
     {
        "names": ["test company 3", "test company 4"],
        "role": "mechanical"
    }
]

В функции контроллера я пытаюсь l oop через это и обновление многих документов и их роли следующим образом:

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-заголовка:

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'

Я пытался выяснить, что лучший способ сделать это. Из-за вызовов asyn c я не могу инициализировать переменную результата снаружи, а затем обновить ее внутри функции карты, а затем использовать ее для отправки ответа. Однако, несмотря на эту ошибку, база данных может обновляться правильно.

1 Ответ

2 голосов
/ 07 августа 2020

Похоже, вы уже знаете, что не можете отправить несколько ответов на один и тот же запрос. Поэтому вместо этого вам нужно собрать все результаты, а затем отправить один ответ. Поскольку у вас есть несколько асинхронных операций, использующих обещания, вы можете использовать Promise.all(), чтобы узнать, когда все они будут выполнены, а затем отправить массив результатов.

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-запрос, даже если есть ошибка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...