我在这里有一些代码,使用firebase auth将用户登录到firebase。我在我的app.js文件中实例化一个新用户,在该对象上调用signIn方法,然后在用户类的signIn方法中,我通过控制台登录从firebase auth返回的凭据。我还将凭证返回给调用它的对象,并再次控制台记录凭证。当我使用async / await时,代码将按预期运行:它将凭据首先登录到signIn方法中,然后在我调用signIn之后再次将其记录在app.js中。
但是,当我尝试使用.then方法进行操作时,我的app.js文件中的console.log在控制台登录User类的signIn方法之前显示为undefined。但是,User类的signIn方法中的控制台日志返回正确的凭据。
我的问题是:为什么控制台记录之前,我的app.js文件中的控制台日志不等待获取凭证?或者至少是控制台记录了诺言?
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();
})
});
最佳答案
首先,您应该注意,async / await基本上只是表示基于Promise的工作流的另一种方法。当您将一个函数标记为异步时,基本上是说该函数将返回一个Promise,而当您在一个异步函数中使用await时,则基本上是说该函数的其余部分将成为.then
回调的一部分。隐含的承诺。
对于您的问题,signIn()
被标记为异步,这意味着它返回一个承诺(这就是为什么signIn().then
不会引发TypeError的原因),并且在其中创建了一个承诺(auth.signInWithEmailAndPassword
),但是promise不与signIn
的隐式Promise绑定,因此隐式Promise立即解决。换句话说,您的signIn
原始版本等效于:
signIn() {
auth.signInWithEmailAndPassword(this.email,this.password).then((cred) => {
console.log(cred);
return cred;
});
return Promise.resolve(undefined);
}
若要解决此问题,如果要在
async
之外使用signIn
,则需要从signIn
删除.then
关键字,并从signIn
返回诺言。例如:signIn() {
return auth.signInWithEmailAndPassword(this.email,this.password).then((cred) => {
console.log(cred);
return cred;
});
}
实际上,以上代码等效于以下异步/等待版本:
async signIn() {
const cred = await auth.signInWithEmailAndPassword(this.email,this.password);
console.log(cred);
return cred;
}
请注意,尽管在事件侦听器中,您不是在等待诺言,所以它会在
e.preventDefault()
诺言完成之前解决。也就是说,您原始的事件处理程序等效于: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);
}
这可能对您没有任何意义,因为DOM事件要么不在乎回调的返回值,要么在乎诺言。这是在某些情况下可能很重要的区别(例如,如果在
.then
内/之后在async
之后调用,则将不起作用)关于javascript - 您可以直接使用.then调用异步函数/方法吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56120119/