Promise is not executing succesfully within a recursively called parent function

Issue

I have the function attemptSearch() which is first ivoked and then it is supposed to call itself recursively until a certain condition is met. The code is only partially working right now. The second console.log() is being called with each iteration, but the console.log() within the function searchForPostcodes() is only called once, during the initial invocation of attemptSearch(), which would suggest none of searchForPostcodes() code is being executed in the following iterations. Not quite sure what I’m doing wrong here.

Just for added context, I have confirmed that the Postcode.find method is functioning fine in isolation. It is a method that belongs to mongoDB->Mongoose Modal

let latMin = lat - 0.0005;
let latMax = lat + 0.0005;
let longMin = long - 0.0005;
let longMax = long + 0.0005;

const searchForPostcodes = new Promise((resolve, reject) => {
  console.log('test')
  Postcode.find({
    lat: {
      $gte: latMin,
      $lte: latMax
    },
    long: {
      $gte: longMin,
      $lte: longMax
    }
  }, (err, postcodes) => {
    if (err) {
      reject(err);
    } else {
      resolve(postcodes);
    }
  });
});
let searchAttempts = 0;

function attemptSearch() {
  latMin = latMin - 0.0005;
  latMax = latMax + 0.0005;
  longMin = longMin - 0.0005;
  longMax = longMax + 0.0005;

  searchForPostcodes
    .then(postcodes => {
      if (postcodes.length > 0) {
        res.json(postcodes);
      } else {
        if (searchAttempts < 100) {
          console.log(searchAttempts, latMin);
          searchAttempts++;
          attemptSearch();
        } else {
          res.status(400).send('No postcodes found');
        }
      }
    })
    .catch(err => {
      res.status(400).send(err);
    });
}
attemptSearch();

Solution

There are multiple problems here. First off, inside of attemptSearch(), you must return the promise inside so you chain them all together. Then, your additional calls to attemptSearch() don’t actually do anything new with searchForPostcodes because that’s a static promise, not a newly generated one. You don’t call your database again, you’re just using the previous promise.

So, I implemented the following changes:

  1. Changed searchForPostcodes into a function that can be executed each time through the recursion.
  2. Switched to use the native promises in your database.
  3. Add return to return SearchForPostcodes().then().catch() so it’s linked into the same promise chain.
  4. Add return to return attemptSearch() so the recursive call is linked into the same promise chain.

Here’s the modified code:

let latMin = lat - 0.0005;
let latMax = lat + 0.0005;
let longMin = long - 0.0005;
let longMax = long + 0.0005;

const searchForPostcodes = function() {
    return Postcode.find({
        lat: {
            $gte: latMin,
            $lte: latMax
        },
        long: {
            $gte: longMin,
            $lte: longMax
        }
    });
}

let searchAttempts = 0;

function attemptSearch() {
    latMin = latMin - 0.0005;
    latMax = latMax + 0.0005;
    longMin = longMin - 0.0005;
    longMax = longMax + 0.0005;

    return searchForPostcodes().then(postcodes => {
        if (postcodes.length > 0) {
            res.json(postcodes);
        } else {
            if (searchAttempts < 100) {
                console.log(searchAttempts, latMin);
                searchAttempts++;
                return attemptSearch();
            } else {
                res.status(400).send('No postcodes found');
            }
        }
    }).catch(err => {
        res.status(400).send(err);
    });
}
attemptSearch();

FYI, if this were my code, I would pass the latXX variables to searchForPostcodes() as function arguments rather than make them higher scoped variables.

Answered By – jfriend00

Answer Checked By – Senaida (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.