Home > Blockchain >  Getting the error 'Cannot set headers after they are sent to the client' in node.js
Getting the error 'Cannot set headers after they are sent to the client' in node.js

Time:01-14

I have a frontend and server-backend, where I send a request to the backend for some book-information. The backend then calls an API for this information and returns it to the frontend. It all works fine at the first request. If I do another request from the frontend it yields the error below.

How can I do such that its possible to keep making a new request from the frontend?

node:internal/errors:478
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:387:5)
    at ServerResponse.setHeader (node:_http_outgoing:644:11)
    at ServerResponse.header (/Users/jeff/Documents/myProject/backend/node_modules/express/lib/response.js:794:10)
    at ServerResponse.send (/Users/jeff/Documents/myProject/backend/node_modules/express/lib/response.js:174:12)
    at ServerResponse.json (/Users/jeff/Documents/myProject/backend/node_modules/express/lib/response.js:278:15)
    at file:///Users/jeff/Documents/myProject/backend/controllers/model.js:22:14
    at file:///Users/jeff/Documents/myProject/backend/controllers/model.js:63:10
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  code: 'ERR_HTTP_HEADERS_SENT'
}
[nodemon] app crashed - waiting for file changes before starting...

showBooks is the entry-point for the rest-call from the frontend.

export const showBooks = async (req, res) => {

   const books = req.body.books;

   await getBooksInfo(books, (err, results) => {
      if (err) {
         res.send(err);
      } else {
         res.json(results);
      }
   });
}

getBooksInfo is then called, which loops through the provided books

const getBooksInfo = async (books, result) => {

   let all_books = [];

   books.forEach(async (book) => {

      if (book.type == "adventure") {

         const on_sale = book.meta.sale;

         if (on_sale == true) {

            let book_authors = book.meta.authors;

            try {
               for (const i in book_authors) { 

                  await book_api(book_authors[i].name, (err, results) => {
                     if (err) {
                        console.log(err);
                     } else {
                        all_books.push(results);
                     }
                  });
               }
            } catch (err) {
               console.log(err);
            }
         }
         result(null, { input: all_books });
      }
   });
}

book_api is responsible for the getting the information on the external rest-point

export const book_api = async (author_name, result) => {

     try {
        const response = await axios.get(`https://book-service.com?author=${author_name}`);
  
        const author_info = response.data.author;
     
         let author = {
            "name" : author_info.name,
            "website" : author_info.website,
         };
        result(null, author);
     } catch (err) {
        result(err, null);
     }
  };

CodePudding user response:

Note that forEach is not designed for asynchronous operations, try to replace books.forEach(async (book) => ... with for (const book of books)...

CodePudding user response:

Note that where you have console.log(err), also place return type, so that once request is completed it will return some result(true or false).

  • Related