0

Basically I'm trying to pull out some data from mongodb, modify it and the send it as a response to the client. To modify the data that I need it takes 2 for loops, inside the second loop a function is being called which edits the data and spits out updated version of it, when thats done original arrays data is being modified and so on. I have 2 counters, one is for the parent for loop, second one is for the child, at the end when it the loop ends it checks if it got passed through all parent and child items using counter and if so the response is being sent the modified array. Problem is the response is being called twice every time resulting in a server crash with the following error:

    events.js:136
      throw er; // Unhandled 'error' event
      ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at validateHeader (_http_outgoing.js:503:11)
    at ServerResponse.setHeader (_http_outgoing.js:510:3)
    at ServerResponse.header (/Users/admin/Documents/projects/stalotenisas/server/node_modules/express/lib/response.js:767:10)
    at ServerResponse.send (/Users/admin/Documents/projects/stalotenisas/server/node_modules/express/lib/response.js:170:12)
    at ServerResponse.json (/Users/admin/Documents/projects/stalotenisas/server/node_modules/express/lib/response.js:267:15)
    at calcStats (/Users/admin/Documents/projects/stalotenisas/server/routes/divisions.js:253:23)
    at Match.getAll (/Users/admin/Documents/projects/stalotenisas/server/routes/divisions.js:146:7)
    at model.Query.<anonymous> (/Users/admin/Documents/projects/stalotenisas/server/node_modules/mongoose/lib/model.js:3928:16)
    at /Users/admin/Documents/projects/stalotenisas/server/node_modules/kareem/index.js:297:21
    at /Users/admin/Documents/projects/stalotenisas/server/node_modules/kareem/index.js:135:16
    at process._tickCallback (internal/process/next_tick.js:150:11)
[nodemon] app crashed - waiting for file changes before starting...

The code:

const divisions = [
  {
    _id: 0,
    name: 'First division',
    teams: [
      {
        name: 'Team A',
        players: [
          'John',
          'Jim',
          'Tom',
          'Jacob'
        ]
      },
      {
        name: 'Team B',
        players: [
          'John',
          'Jim',
          'Tom',
          'Jacob'
        ]
      }
    ],
    players: [],
    tournament: false
  },
  {
    _id: 1,
    name: 'Second division',
    teams: [
      {
        name: 'Team A',
        players: [
          'John',
          'Jim',
          'Tom',
          'Jacob'
        ]
      },
      {
        name: 'Team B',
        players: [
          'John',
          'Jim',
          'Tom',
          'Jacob'
        ]
      }
    ],
    players: [],
    tournament: false
  },
  {
    _id: 2,
    name: 'Third division',
    teams: [
      {
        name: 'Team A',
        players: [
          'John',
          'Jim',
          'Tom',
          'Jacob'
        ]
      },
      {
        name: 'Team B',
        players: [
          'John',
          'Jim',
          'Tom',
          'Jacob'
        ]
      }
    ],
    players: [],
    tournament: false
  }
]

calcTournamentStats = (player, division_id, callback) => {
  setTimeout(() => {
    callback(null, 'Anthony');
  }, 2000);
}

calcStats = (team, division_id, callback) => {
  setTimeout(() => {
    callback(null, 'Team F');
  }, 2000);
}

getDivisionsByLeagueId = (callback) => {
  let count = 0;
  if (divisions.length === 0) {
    return callback('error', null);
  }
  else {
    divisions.forEach((division, dindex) => {
      count++;
      let inner_count = 0;
      if (division.tournament) {
        division.players.forEach((player, index) => {
          calcTournamentStats(player, division._id, (err, result) => {
            inner_count++;
            divisions[dindex].players[index] = result;
            if (count === divisions.length && inner_count === division.players.length) {
              callback(null, 'response which should be caled once');
            }
          });
        });
      }
      else {
        division.teams.forEach((team, index) => {
          calcStats(team, division._id, (err, result) => {
            inner_count++;
            console.log(count +' - '+ divisions.length +' || '+ inner_count +' - '+ division.teams.length);
            divisions[dindex].teams[index] = result;
            if (count === divisions.length && inner_count === division.teams.length) {
              callback(null, 'response which should be caled once');
            }
          });
        });
      }
    });
  }
};

getDivisionsByLeagueId((err, res) => {
  console.log(res);
});
Eqls
  • 1
  • 2
  • Hi! I don't think we can help you without knowing what the data looks like. Please update your question with a [mcve] demonstrating the problem, ideally a **runnable** one using Stack Snippets (the `[<>]` toolbar button; [here's how to do one](https://meta.stackoverflow.com/questions/358992/)). Obviously, you'll need to use placeholders for `calcStats` and `calcTournamentStats` (which will need to use `setTimeout` to emulate their asynchronous behavior). – T.J. Crowder May 11 '18 at 10:31
  • Where are you increasing `count` ?! – Jonas Wilms May 11 '18 at 10:32
  • @JonasW. sorry, updated the code. It was there in my code, so that's not the problem – Eqls May 11 '18 at 13:15
  • @T.J.Crowder Hi, I will update the thread. Thanks! – Eqls May 11 '18 at 13:16

0 Answers0