javascript - 您可以直接使用 .then 调用异步函数/方法吗?

标签 javascript firebase asynchronous promise

我这里有一些代码,我使用 firebase auth 将用户登录到 firebase。我在 app.js 文件中实例化一个新用户,调用该对象的 signIn 方法,然后在用户类的 signIn 方法中,我通过控制台登录 firebase 身份验证的返回凭据。我还将凭证返回给调用它的对象,并再次通过控制台记录凭证。当我使用 async/await 时,代码按照我的预期运行:它首先在 SignIn 方法中记录凭据,然后在我调用 SignIn 后再次在 app.js 中记录凭据。

但是,当我尝试使用 .then 方法执行此操作时,app.js 文件中的 console.log 在 User 类的 SignIn 方法中的控制台日志之前显示未定义。但是,User 类的signIn 方法中的控制台登录返回正确的凭据。

我的问题是:为什么我的 app.js 文件中的控制台日志不等待在控制台日志记录之前获取凭据?或者至少控制台记录一个 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();
            })
        });

最佳答案

首先,您应该注意 async/await函数本质上只是表达基于 Promise 的工作流程的另一种方式。当你将一个函数标记为异步时,你基本上是在说这个函数将返回一个 Promise,而当你在异步函数中使用 wait 时,你基本上是在说这个函数的其余部分将成为 的一部分。 then 该隐式 Promise 的回调。

回答你的问题,signIn() 被标记为异步,这意味着它返回一个 promise (这就是为什么 signIn().then 不会抛出 TypeError ),并在其中创建一个 Promise (auth.signInWithEmailAndPassword),但该 Promise 并未与 signIn 的隐式 Promise 绑定(bind),因此隐式 Promise 会立即解析。换句话说,您的 signIn 原始版本相当于:

signIn() {
  auth.signInWithEmailAndPassword(this.email,this.password).then((cred) => {
    console.log(cred);
    return cred;
  });
  return Promise.resolve(undefined);
}

要修复此行为,您需要从 signIn 中删除 async 关键字,并从 signIn 返回 promise (如果您想使用 .then 之外。例如:

signIn() {
  return auth.signInWithEmailAndPassword(this.email,this.password).then((cred) => {
    console.log(cred);
    return cred;
  });
}

上面的代码实际上相当于这个 async/await 版本:

async signIn() {
  const cred = await auth.signInWithEmailAndPassword(this.email,this.password);
  console.log(cred);
  return cred;
}

请注意,尽管在您的事件监听器中,您并未等待 Promise,因此它将在 signIn Promise 完成之前解析。也就是说,你原来的事件处理程序相当于:

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 事件要么不关心回调的返回值,要么尊重 promise 。这是一个在某些情况下可能很重要的区别(例如,如果您在 .then 内部调用它/在 async 之后调用它,e.preventDefault() 将不起作用)

关于javascript - 您可以直接使用 .then 调用异步函数/方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56120119/

相关文章:

javascript - Firebase 验证 - 可选属性

ios - 设备无法使用 Firebase 身份验证电话号码

c# - ASP.NET 线程 : should I use the pool for DB and Emails actions?

javascript - 异步加载库时如何处理依赖关系?

javascript - 由于连接循环,运行 Paho javascript 示例导致网络连接崩溃

Javascript/Html/CSS 转换切换和 slideToggle

javascript - 如何打开父级中的所有window.open onclick函数

javascript - 使用从 forEach 循环中提取的国家代码从数组中获取国家名称

javascript - 如何将带有自定义 ID 的文档添加到 firestore

javascript - Javascript 中的异步循环