skip to Main Content

I ran into a weird problem with a .then off an asyc function’s promise.
I call to a function to check the user’s google id against my database to see if they have an account on the network.

Login(DecodedGoogleCredentials.sub).then((localID)=> {//Login returns a promise with the local id for the database

             console.log(localID);//used to confirm id
             sessionStorage.setItem("CurrentUserID", localID);//set for refresh

             setID(localID);//set to recall App
             setLogin(true);//set to ensure it will be recalled

       });//end of Login().then(()=>{});

In my asnc function, I get the local id I expect, but when I check it with console.log(localID); in my .then, it writes a result of undefined.

Here is the async function:

async function Login(GoogleID) {//Called from App()
    
    const idQuery = query(idRef, where("id", "==", GoogleID.toString()));//build query for user's id
    const idDoc = await getDocs(idQuery);//get doc found in query. There should only be one
    
    var userFound = false;//user is not found
    
    idDoc.forEach((doc) => {//loop through docs

        userFound = true;//user is found  
        const localID = doc.data().localID;
        console.log(localID)
        try {
            return localID;
        }
        catch(e) {
            console.log(e)
        }
        
    });
    //there is no user so far
    if (userFound==false) {//create new user if user is not found
        
       return await CreateUser(GoogleID);//create the login
    }
}//end of Login(id)

The console.log(localID) here works perfectly and writes the value that I expect. Anyone know why I’m getting a different result in my .then function?

Answer:

Thanks everyone for your help. The problem stemmed from me returning from a foreach.
here is what my new code looks like, which functions correctly

async function Login(GoogleID) {//Called from App()
    
    const idQuery = query(idRef, where("id", "==", GoogleID.toString()));//build query for user's id
    const idDoc = await getDocs(idQuery);//get doc found in query. There should only be one

    var foundDoc;
    idDoc.forEach((doc) => {//loop through docs
       foundDoc = doc
    });
    if (foundDoc != null) {
        const localID = foundDoc.data().localID;
        
       
            return localID;
        
    }
   else {//create new user if user is not found
        
       return CreateUser(GoogleID);//create the login
    }
}//end of Login(id)

2

Answers


  1. You return from the callback for forEach(), not from the function. You could fix:

    return idDoc[0]?.data().localID ?? CreateUser(GoogleID);
    

    Here we expect that idDoc contains objects. If there’s no an object with index 0 (dDoc[0]?.) then we create a new user.

    You don’t need Array::forEach() here since you check the first element only – there’s nothing to iterate to find an array item beyond the index 0.

    Also you don’t need return await since it’s waste of time to wait a promise that will be waited or even discarded later, not good for performance potentially.

    Also don’t use var – it’s legacy and buggy.

    Login or Signup to reply.
  2. The return statement in the forEach loop exists the function you are passing to it, and not the main Login function.

    Also the try/catch around it is useless, since return followed by a variable will never throw.

    Consider using Array.prototype.find instead:

    async function login(id) {
        const idQuery = query(idRef, where("id", "==", id.toString()));
        const idDoc = await getDocs(idQuery);
        const foundID = idDoc.find((doc) => doc.data().localID);
        if (foundID) {
            return foundID;
        }
        return CreateUser(id);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search