Return a value from nested function

const shortUrlNumber = createShortUrlNumber();
console.log("Number RETURNED  " + shortUrlNumber);

function createShortUrlNumber() {
// create random number
  const shortNumber = Math.floor((Math.random() * 10) + 1);

// search database for any document with that shortNumber as key_url
  UrlConverter.findOne({ "key_url": shortNumber }, function (err, data) {
    if (err) {
      return handleError(err);
    } else if (data) {
      console.log("FOUND A DOCUMENT:  " + data);
      // call function again to create a new random number and search database
      createShortUrlNumber();
    } else {
      console.log("FOUND NONE: return shortNumber ");
      return shortNumber;
    }
  })
}

If I return shortNumber outside of UrlConverter.findOne() it never gets checked against the database.

I’m wondering how do I return shortNumber so that shortUrlNumber has that value?

The problem isn’t actually when you find an unused number, it’s when you find a USED one and re-call createShortUrlNumber() again. If you find a number, you’re callling the function, but you aren’t returning the value of that nested call. Change that one line to:

return createShortUrlNumber();

and you should get what you’re expecting.

Of course, you realize you’re limiting yourself to exactly ten possible shortUrlNumbers? Just pointing out the obvious, but still.

This did not solve the issue.

But I have noticed using console logs that the function is not completed before the returned value is trying to be used outside the createShortUrlNumber function.

If I console log shortUrlNumber after it’s set (line 2), the FOUND NONE console log happens after.

`
Number RETURNED undefined

FOUND NONE: return shortNumber
`
So now I think this must be an async process.

I’ve had similar problems, without seeing more code it’s hard to suggest a way to help, but it probably is an async issue. That can be solved with Promises or await/async (but I haven’t really mastered those). What I had to do was really think about the order my code was executing. I read a quote somewhere that said something like
“javascript, like life, waits for no man”
So your your logs are right. I haven’t tested this but if you moved the log to here

} else {
      console.log("FOUND NONE: return shortNumber ");
      console.log("Number RETURNED  " + shortUrlNumber);
      return shortNumber;

I suspect Number RETURNED will not be undefined.

So if in your code you are trying to use shortUrlNumber immediately it won’t work because it is undefined.

You could maybe put a var shortUrlNumber in your function

function createShortUrlNumber() {
var shortUrlNumber;
// create random number
  const shortNumber = Math.floor((Math.random() * 10) + 1);

and then

} else {
      console.log("FOUND NONE: return shortNumber ");
      shortUrlNumber = shortNumber;
      //then do something with shortUrlNumber here
    }

But like I said this is untested and maybe Promises or await/async is the better route.

1 Like

Since I posted this I rewrote the code to avoid the functional programming approach. I did a lot of if/else inside collection.find(), which is not what I wanted.
I am going to try and refactor to deal with the async aspect.
Might as well push myself into having a go.