javascript recursion method?

Viewed 72

I need to do one method linkedIn like that generates automatically a username after registering.

To do so i followed this logic:

1 - get the name and surname and make a join (if name is Tom and surname Hanks then base username would be tomhanks)

2 - I check if that username already exists in the database.

2.1 if it doesn't exist then I return it

2.2 if it exists then I add a suffix and recall the function with the parameter base username + suffix

That's it.

I did the following code:

    export const buildUsername = async (value) => {
        const { db } = await connectToDatabase(URI, DATABASE);
        let obj = await db.collection(COLLECTION).findOne({username: value});
        if(obj != null) {
            suffix +=1;
            buildUsername(value + suffix)
        }else{
            suffix = 1;
            return value;
        }
    }

In the post method I did the following:

let username = buildUsername(user.name + user.surname)
//I pretend username to contain a unique username so i could register it into the DB

The problem is that this method doesn't work well. if the username is unique at the first step then it returns it right. If there need to do some recursions then 'username' is undefined. I have to say that if I log the value before returning it, it seems to work and logs the base username with some numbers after..

What do you think? Is it the right method to do it? Or I just have to think differently?

Thank you very much!

2 Answers

In the case that the username is not unique, you trigger the if branch of your if-else statement. In the if branch you never return a value, which is why you are getting undefined for the username.

Add a return statement before you recursively call the buildUsername function and it should work:

export const buildUsername = async (value) => {
    const { db } = await connectToDatabase(URI, DATABASE);
    let obj = await db.collection(COLLECTION).findOne({username: value});
    if(obj != null) {
        suffix +=1;
        return buildUsername(value + suffix)
    }        
    suffix = 1;
    return value;        
}

JackGore's answer solves the missing return problem but leaves several issues in the code -

  1. reconnects to the database on each recurrence
  2. leaks a global variable suffix
  3. does not generate usernames sequentially

Here's a way to fix the remaining problems -

async function buildUsername (value)
{ const { db } =
    await connectToDatabase(URI, DATABASE) // <- once

  async function loop (suffix)
  { const user =
      await db
        .collection(COLLECTION)
        .findOne({username: value + suffix })

    if (user != null)
      return loop(Number(suffix) + 1) // <- recur
    else
      return value + suffix
  }

  return loop('') // <- initial suffix
}

This answer will check usernames sequentially, without skipping any values -

helloworld
helloworld1
helloworld2
helloworld3
helloworld4
...
helloworld9
helloworld10
helloworld11
helloworld12

Whereas your original program will skip many possibilities and results in very long usernames -

helloworld
helloworld1
helloworld12
helloworld123
helloworld1234
...
helloworld123456789
helloworld12345678910
helloworld1234567891011
helloworld123456789101112
Related