Javascript 你能直接用.调用异步函数/方法吗?
这里有一些代码,我使用firebase auth将用户登录到firebase。我在app.js文件中实例化一个新用户,调用该对象上的signIn方法,然后在user类的signIn方法中,我在控制台上记录firebase auth的返回凭证。我还将凭证返回给调用它的对象,并再次记录凭证。当我使用async/await时,代码运行与我预期的一样:它首先将凭证记录在signIn方法中,然后在我调用signIn之后再次记录在app.js中 但是,当我尝试使用.then方法时,我的app.js文件中的console.log在User类的sign方法中的console log之前显示为undefined。但是,User类的signIn方法中的控制台日志返回正确的凭据 我的问题是:为什么我的app.js文件中的控制台日志不在控制台日志记录之前等待获取凭据?或者至少是一个承诺Javascript 你能直接用.调用异步函数/方法吗?,javascript,firebase,asynchronous,promise,Javascript,Firebase,Asynchronous,Promise,这里有一些代码,我使用firebase auth将用户登录到firebase。我在app.js文件中实例化一个新用户,调用该对象上的signIn方法,然后在user类的signIn方法中,我在控制台上记录firebase auth的返回凭证。我还将凭证返回给调用它的对象,并再次记录凭证。当我使用async/await时,代码运行与我预期的一样:它首先将凭证记录在signIn方法中,然后在我调用signIn之后再次记录在app.js中 但是,当我尝试使用.then方法时,我的app.js文件中的c
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时,基本上是说这个函数将返回一个承诺,而当您在一个async函数中使用Wait时,基本上是说这个函数的其余部分将是
的一部分。然后回调该隐式承诺
说到你的问题,signIn()
被标记为异步,这意味着它返回一个承诺(这就是为什么signIn()。然后
不会抛出一个TypeError),在它里面你创建了一个承诺(auth.signInWithEmailAndPassword
),但是这个承诺与signIn
的隐含承诺没有联系,因此,隐含的承诺会立即得到解决。换句话说,您的登录的原始版本相当于:
signIn() {
auth.signInWithEmailAndPassword(this.email,this.password).then((cred) => {
console.log(cred);
return cred;
});
return Promise.resolve(undefined);
}
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);
}
若要修复此行为,需要从signIn
中删除async
关键字,并从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;
}
请注意,在事件侦听器中,您并不是在等待承诺,因此它将在signIn
承诺完成之前解决。也就是说,您的原始事件处理程序相当于:
signIn() {
auth.signInWithEmailAndPassword(this.email,this.password).then((cred) => {
console.log(cred);
return cred;
});
return Promise.resolve(undefined);
}
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事件或者不关心回调的返回值,或者不尊重承诺。这一区别在某些情况下可能很重要(例如,e.preventDefault()
如果在中调用它,它将不起作用。然后,
/在异步
之后)首先,您应该注意,/功能本质上只是表达基于承诺的工作流的另一种方式。当您将一个函数标记为async时,基本上是说这个函数将返回一个承诺,而当您在一个async函数中使用Wait时,基本上是说这个函数的其余部分将是的一部分。然后回调该隐式承诺
说到你的问题,signIn()
被标记为异步,这意味着它返回一个承诺(这就是为什么signIn()。然后
不会抛出一个TypeError),在它里面你创建了一个承诺(auth.signInWithEmailAndPassword
),但是这个承诺与signIn
的隐含承诺没有联系,因此,隐含的承诺会立即得到解决。换句话说,您的登录的原始版本相当于:
signIn() {
auth.signInWithEmailAndPassword(this.email,this.password).then((cred) => {
console.log(cred);
return cred;
});
return Promise.resolve(undefined);
}
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);
}
若要修复此行为,需要从signIn
中删除async
关键字,并从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;
}
请注意,在事件侦听器中,您并不是在等待承诺,因此它将在signIn
承诺完成之前解决。也就是说,您的原始事件处理程序相当于:
signIn() {
auth.signInWithEmailAndPassword(this.email,this.password).then((cred) => {
console.log(cred);
return cred;
});
return Promise.resolve(undefined);
}
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事件或者不关心回调的返回值,或者不尊重承诺。这一区别在某些情况下可能很重要(例如,e.preventDefault()
如果在内部调用它,则它将不起作用。然后在异步后
)您的登录()
需要在内部返回承诺。当前它不返回任何内容,这就是为什么user.signIn().then()
根本不应该工作的原因。因为signIn不返回承诺,所以它不是链的一部分。您的signIn()
需要在内部返回承诺。目前它不返回任何内容,这就是为什么user.signIn().then()
根本不应该工作的原因。因为signIn不返回承诺,所以它不是链的一部分。太棒了。它现在起作用了,我需要回报这个承诺,这是有道理的。为了确保我完全理解,请注意最后一点“尽管在您的事件侦听器中,您没有等待承诺,因此它将在签名
承诺完成之前返回。”通过在我的签名
中返回承诺,我将在我的事件监听器中有效地等待这个承诺?@user2954945我已经更新了我的答案,以提供更完整的解释。真棒的解释!谢谢!我从中学到了很多。太棒了。它现在起作用了,我需要回报这个承诺,这是有道理的。为了确保我完全理解,请注意最后一点“尽管在您的事件侦听器中,您没有等待承诺,因此它将在签名
承诺完成之前返回。”通过在我的签名
中返回承诺,我将在我的事件监听器中有效地等待这个承诺?@user2954945我已经更新了我的答案,以提供更完整的解释。真棒的解释!谢谢!我学到了很多