Можете ли вы вызвать асинхронную функцию / метод напрямую с помощью .then? - PullRequest
0 голосов
/ 14 мая 2019

У меня есть некоторый код, где я регистрирую пользователя в firebase, используя аутентификацию firebase. Я создаю экземпляр нового пользователя в своем файле app.js, вызываю метод signIn для этого объекта, затем в моем методе signIn класса пользователя я консоль регистрирую возвращенные учетные данные из firebase auth. Я также возвращаю учетные данные объекту, который его вызвал, и консоль снова регистрирует учетные данные. Когда я использую async / await, код выполняется так, как я ожидал: сначала он регистрирует учетные данные в методе signIn, а затем снова в app.js сразу после того, как я вызываю signIn.

Однако, когда я пытаюсь сделать это, используя подход .then, файл console.log в моем файле app.js показывает undefined до входа в консоль в методе signIn класса User. Однако консольный журнал в методе signIn класса User возвращает правильные учетные данные.

Мой вопрос: почему журнал консоли в моем файле 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();
            })
        });

1 Ответ

2 голосов
/ 14 мая 2019

Прежде всего, вы должны заметить, что async / await функционирует, по сути, как еще один способ выражения рабочих процессов на основе Promise.Когда вы помечаете функцию как асинхронную, вы в основном говорите, что эта функция будет возвращать Promise, а когда вы используете await внутри асинхронной функции, вы в основном говорите, что остальная часть этой функции будет частью обратного вызова .then.этого неявного обещания.

Возвращаясь к вашему вопросу, signIn() помечается как асинхронный, что означает, что он возвращает обещание (именно поэтому signIn().then не генерирует ошибку TypeError), и внутри него высоздание обещания (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если вы хотите использовать .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.То есть ваш оригинальный обработчик событий эквивалентен:

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() не будет работать, если вы вызовете его внутри .then / после async)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...