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