Stephen
Stephen

Reputation: 1183

Express - NodeJS - Error: Cannot set headers after they are sent to the client

I have a problem with a project. I have a external API that I need to call in order to get some data. This API call works in two steps. First I send them my data. They calculate a result within 6-12 seconds. So I have added a Interval that executes every second and asks the external API for the result.

I send back a 400 status code before I ask for the result. So that the front end application can go on and it doesn't need to wait for the result to be calculated.

But I always get an error stating that I cannot set headers after they are sent to the client.

I have tried to remove the response inside the catch block. But this does not help as well. If I remove the headers from the second Axios call I get a 'Unauthorized' error from the externel server.

I have also tried to create a axios instance at the start of the function and set the headers there. Then used that instance for both calls. But here still the error persists.

(node:37609) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:561:11) at ServerResponse.header (/Users/stephen/Documents/projects/test-api/node_modules/express/lib/response.js:771:10) at ServerResponse.send (/Users/stephen/Documents/projects/test-api/node_modules/express/lib/response.js:170:12) at ServerResponse.json (/Users/stephen/Documents/projects/test-api/node_modules/express/lib/response.js:267:15) at /Users/stephen/Documents/projects/test-api/routes/blue.js:143:45 at processTicksAndRejections (internal/process/task_queues.js:95:5) at async Timeout._onTimeout (/Users/stephen/Documents/projects/test-api/routes/blue.js:107:9) (Use node --trace-warnings ... to show where the warning was created) (node:37609) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2) (node:37609) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

router.post('/calculate/:plotId', verify, async (req, res) => {
  const info = req.body;

  const auth = `Basic ${Buffer.from(`${process.env.USERNAME}:${process.env.PASSWORD}`).toString('base64')}`;

  const headers = {
    Authorization: auth,
    'Content-Type': 'text/plain; charset=utf-8',
    Host: 'test.app.be',
  };

  await axios.post('https://test.app.be/label', info, {
    headers,
  }).then(async (response) => {
    res.status(201).json({
      message: 'blue label sended!',
    });

    async function getResult(key) {
      const interval = setInterval(async () => {
        await axios.get(`https://test.app.be/result/${key}`, {
          headers,
        }).then(async (resp) => {
          // Calculating Blue score failed
          if (resp.data.status && resp.data.status === 'failed') {
            clearInterval(interval);
          }

          const data = resp.data.ontwerp;

          if (!data) return;

          clearInterval(interval);
        }).catch((error) => {
          res.status(400).json({
            message: error,
          });

          clearInterval(interval);
        });
      }, 1000);
    }

    getResult(response.data[0].result_id);
  }).catch((error) => {
    res.status(400).json({
      error,
    });
  });
});

Upvotes: 1

Views: 2095

Answers (1)

Fide
Fide

Reputation: 1197

axios.post....res.status(201) - first res.status

async function getResult(key) ... axios.get...catch(...res.status(400)) - second

In case you get the axios.post resolved and axios.get rejected, you turn into second res.status calling.

res.send or res.status does not work as return - the function runs on.

Upvotes: 2

Related Questions