0

I'm trying to run a for loop over a mongo query to continuously retrieve data from the database. After it's retrieved I then try and push it to an array then res.send(array) to avoid the unhandled promise rejection. But instead, the data isn't being pushed into the array.

router.get('/results/:week',function(req,res,next){
var week = req.params.week - 1;
var results = [];
for(week; week>0; week--){
    Fixture.find({'week':week}).then(function(fixture){
        results.push(fixture);
    });
}
res.send(results);

The Fixture model contains a variable week, and I want to retrieve all the results(fixtures) from a certain week downwards. The result given is and empty array [] and if I res.send(fixture) I get the unhandled promise rejection warning. Please help and thank you.

igolo
  • 521
  • 1
  • 4
  • 4

3 Answers3

0

Your res.send needs to be in the callback.

Also, after finding this article, I am thinking maybe this could be what you are needing (notice, the "let week..."):

router.get('/results/:week',function(req,res,next){
var results = [];
for(let week = req.params.week -1; week>0; week--){
    Fixture.find({'week':week}).then(function(fixture){
        results.push(fixture);
        if (week == 1) {
            res.send(results);
        }
   });
}
Jeff Matthews
  • 602
  • 2
  • 7
  • 17
  • This worked, thank you so much. Why let instead of var? if I may ask – igolo Feb 02 '18 at 09:37
  • Click the article link I referenced. var is global scope. let is block scope. It's worth the read. I learned something new, too! ;-) – Jeff Matthews Feb 02 '18 at 09:38
  • One thing to watch for is that you are making several async calls in a loop. Since they are async, I wonder whether there is any guarantee they will complete in the order they are started. Read at the end of this previous [SO answer](https://stackoverflow.com/questions/11488014/asynchronous-process-inside-a-javascript-for-loop). – Jeff Matthews Feb 02 '18 at 09:45
0

This is related to the order or execution in Javascript. I would recommend you to have a look on this book series, there is a lot of useful insights!

You could make a workaround in your code, like the following:

router.get('/results/:week',function(req,res,next){
var week = req.params.week - 1;
var results = [];
for(week; week>0; week--){
    Fixture.find({'week':week}).then(function(fixture){
        results.push(fixture);
    });
}

if(week == 0)
   res.send(results);
else
   res.send([]);
Claudio Busatto
  • 721
  • 7
  • 17
0

You getting empty array as result because of async nature of request to mongodb.

At first I think you need to check that you week parameter is number

router.get('/results/:week',function(req,res,next){
    if(!parseInt(req.params.week))
        res.send("Week param not a number");
    ...

Instead of using async function inside loop you can use mongoose built in functions for searching multiple results

router.get('/results/:week',function(req,res,next){
    if(!parseInt(req.params.week))
        res.send("Week param not a number");

    let week = parseInt(req.params.week);

    // Fixture.find(week: {$lt: week}).

    // or

    //Fixture.find().where('week').lt(week).

    // or

    Fixture.find().lt('week', week).then(function(fixtures){
        res.send(fixtures);
    });
}

Or with loop, if you prefer that way

router.get('/results/:week',function(req,res,next){

    if(!parseInt(req.params.week))
        res.send("Week param not a number");

    let week = parseInt(req.params.week)-1;
    let weeks = [];
    for(week; week > 0; week--){
        weeks.push(week);
    }

    Fixture.find().in('week', weeks)
        .then(function(fixtures){
            res.send(fixtures);
        });
}

P.S. In all described cases at list you will decrease amount of requests.

Georgiy Dubrov
  • 408
  • 2
  • 7