Как заставить «onAuthStateChanged» ждать, пока «currentUser.updateProfile» не завершится sh? - PullRequest
0 голосов
/ 01 августа 2020

У меня проблема с регистрацией пользователей в моем приложении Vue ... Когда пользователь регистрируется, я хочу запустить updateProfile, чтобы добавить больше пользовательских данных, а после этого в onAuthStateChanged в моем основном. js сохраните все эти пользовательские данные в vuex для использования в моем приложении, но onAuthStateChanged выполняется перед updateProfile, поэтому в vuex displayName и photoURL не определены.

Как я могу сделать onAuthStateChanged подождите, чтобы updateProfile завершилось sh?

У меня есть эта функция в моем регистре. vue компонент:

register() {
      firebase
        .auth()
        .createUserWithEmailAndPassword(this.email, this.password)
        .then(user => {
          firebase
            .auth()
            .currentUser.updateProfile({
              displayName: this.displayName,
              photoURL: this.photoURL
            })
            .then(() => {
              db.collection("users")
                .doc(user.user.uid)
                .set({
                  email: this.email,
                  displayName: this.displayName,
                  realName: this.realName,
                  photoURL: this.photoURL
                })
                .then(() => {
                  console.log(user);
                  this.$router.replace("/");
                })
                .catch(err => {
                  this.errorMessage = err.message;
                });
            })
            .catch(err => {
              this.errorMessage = err.message;
            });
        })
        .catch(function(error) {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          if (errorCode == "auth/weak-password") {
            alert("The password is too weak.");
          } else {
            alert(errorMessage);
          }
          console.log(error);
        });
    }
  }

И это есть в моем основном. js:

let app = "";

firebase.auth().onAuthStateChanged((user) => {
  store.dispatch("fetchUser", user);
  if (!app) {
    new Vue({
      router,
      store,
      render: (h) => h(App),
    }).$mount("#app");
  }
});

1 Ответ

0 голосов
/ 01 августа 2020

Причина, по которой вы получаете undefined, вероятно, связана с тем, что вы не возвращаете асинхронные функции из метода register.

В настоящее время у вас есть это

register() {
      firebase // undefined as you don't return anything
        .auth()
        .createUserWithEmailAndPassword(this.email, this.password)
        .then(user => {
          firebase
            .auth()
            .currentUser.updateProfile({
              ....
            })
            .then(() => { // undefined as you don't return in the previous then block
              db.collection("users")
                .doc(user.user.uid)
                .set({
                  ......
                })
                .then(() => { // undefined because you don't return in the previous then block
                 ....
                })
                .catch(err => {
                 ...
                });
            })
            .catch(err => {
              ....
            });
        })
        .catch(function(error) {
          ....
        });
    }
  }

Сделайте это

import { EventBus } from './eventBus.js';

register() {
  EventBus.$emit('user-registration-causes-auth-change', true)  // set this to true when the registration starts so that when eventbus listens to it in main.js, it won't update user profile (alternatively, replace with let self = this)
// (if following alternative route, this.isRegistrationTriggeringAuthStateChange = true;)
  return firebase
  .auth()
   ....
   .then(user => {
          return firebase
            .auth()
            .currentUser....
            .then(() => {
              return db.collection("users")
                ....
                .set({
                  ......
                })
                .then(() => {
                  EventBus.$emit('user-registration-causes-auth-change', false) // set it to false after you have finised updating the user profile.  
                   // if following alternative route, self.isRegistrationTriggeringAuthStateChange = false;
                })
       })
    })
}

eventBus. js

import Vue from 'vue';
export const EventBus = new Vue(); // initialise an event bus here and export it so that it could be used in other files

Основной. js

import Vue from 'vue';
import { EventBus } from './eventBus.js';

let app
auth.onAuthStateChanged(async() => {
  if (!app) {
    app = new Vue({
      router,
      store,
      data: {
       isRegistrationTriggeringAuthStateChange: false; // initialise it to false so that when you load the page, it won't be hindered from dispatching "fetchUser" if there's a user.
      },
      render: h => h(App)
    }).$mount('#app')
  }
  
  EventBus.$on('user-registration-causes-auth-change', (payload) => {
    app.isRegistrationTriggeringAuthStateChange = payload;
  })

  await Vue.$nextTick() // wait for the DOM to update
  
  if (user && !app.isRegistrationTriggeringAuthStateChange) { // put the conditional here
    store.dispatch("fetchUser", user);
  }
})

EventBus.$off('user-registration-causes-auth-change', (payload) => { // this could be extracted into a handler
  app.isRegistrationTriggeringAuthStateChange = payload;
})

Это приблизительный код, но его цель - передать информацию. Можете убирать как хотите.

...