Reputation: 121
I have some code here where I am logging a user into firebase using firebase auth. I instantiate a new user in my app.js file, call the signIn method on that object, then in my signIn method of the user class, i am console loggin the return credential from firebase auth. I am also returning the credential to the object that called it and console logging the credential again. When I use async / await, the code runs just as I expect: it logs the credential in the signIn method first, then again in the app.js right after I call signIn.
However, when I try to do it using the .then approach, the console.log in my app.js file shows undefined before the console log in the signIn method of the User class. However, the console log in the signIn method of the User class returns the correct credential.
My question is: why isn't the console log in my app.js file waiting to get the credential before console logging? Or at least console logging a promise?
class User {
constructor(email, password){
this.email = email;
this.password = password;
this.cred;
}
async signUp(){
const cred = await auth.createUserWithEmailAndPassword(this.email, this.password);
return cred;
}
async signIn() {
auth.signInWithEmailAndPassword(this.email,this.password).then(cred=>{
console.log(cred);
return cred;
});
//this async/await code below works as expected
// const cred = await auth.signInWithEmailAndPassword(this.email,this.password);
// console.log(cred);
// return cred;
}
signOut(){
}
}
export default User
// beginning of my app.js file
loginForm && loginForm.addEventListener('submit', async e => {
e.preventDefault();
const user = new User(loginForm.email.value,loginForm.password.value);
//const cred = await user.signIn(); // this async/await code works fine
//console.log(cred);
user.signIn().then(cred => {
console.log(cred); // this console.log fires before the console.log in signIn() and returns undefined
loginForm.reset();
})
});
Upvotes: 0
Views: 199
Reputation: 149040
First off, you should note that async/await functions essentially just another way to express Promise-based workflows. When you mark a function as async, you're basically saying that this function will return a Promise, and when you use await within an async function, you're basically saying the rest of this function will be part of the .then
callback of that implicit Promise.
Getting to your question, signIn()
is marked as async, meaning it returns a promise (which is why signIn().then
doesn't throw a TypeError), and inside it you're creating a promise (auth.signInWithEmailAndPassword
), but that promise is not tied to the implicit Promise of signIn
, so the implicit promise resolves immediately. In other words, your original version of signIn
is equivalent to:
signIn() {
auth.signInWithEmailAndPassword(this.email,this.password).then((cred) => {
console.log(cred);
return cred;
});
return Promise.resolve(undefined);
}
To fix this behavior, you need to remove the async
keyword from signIn
and return the promise from signIn
if you want to use .then
outside of it. For example:
signIn() {
return auth.signInWithEmailAndPassword(this.email,this.password).then((cred) => {
console.log(cred);
return cred;
});
}
The above code is, in fact, equivalent to this async/await version:
async signIn() {
const cred = await auth.signInWithEmailAndPassword(this.email,this.password);
console.log(cred);
return cred;
}
Note though that in your event listener, you're not awaiting the promise, so it will resolve before the signIn
promise is completed. That is to say, your original event handler is equivalent to:
e => {
e.preventDefault();
const user = new User(loginForm.email.value,loginForm.password.value);
user.signIn().then(cred => {
console.log(cred);
loginForm.reset();
});
return Promise.resolve(undefined);
}
This is probably doesn't mean anything for you, since DOM events either don't care about the return value of the callback or respect promises. It's a distinction that could be important in some scenarios (e.g. e.preventDefault()
won't work if you call it inside a .then
/ after an async
)
Upvotes: 2