Как ждать изменения состояния перед выполнением следующего действия в Vuex - PullRequest
1 голос
/ 03 марта 2020

Я пытаюсь войти и получить имя пользователя одновременно. Вот как это работает:

  1. Первое действие login получает токен доступа и обновляет state.accessToken
  2. Используя state.accessToken Мне нужно одновременно получать данные пользователя (fetchUser) при нажатии входа в систему, однако при выполнении fetchUser state.accessToken по-прежнему null, поскольку действия асинхронны. Какова лучшая практика, чтобы ждать изменения состояния перед выполнением следующего действия? Я попытался найти примеры, но найденные решения не применимы для моего случая.

store. js

const store = new Vuex.Store({

state: {
  accessToken: null,
  user: null
},

mutations: {
  authUser (state, userData) {
    state.accessToken = userData.accessToken
  },
  storeUser (state, user) {
    state.user = user
  }
}

actions: {
  login({commit}, authData) {
    axios.post("http://example.com/token/create/", {
        email: authData.email,
        password: authData.password
      })
      .then(res => {
        commit('authUser', {
          accessToken: res.data.access
        })
      })
  },
  fetchUser({commit, state}) {
    axios.get("http://example.com/api/auth/v1/me/", {
      headers: {Authorization: "Bearer "  + state.accessToken}
    })
    .then(res => {
      commit('storeUser', res.data.user)
    })
  }
}

getters: {
  user (state) {
    return state.user
  },
  isAuthenticated(state) {
    return state.accessToken !== null
  }  
}
})

логин. vue

<template>
  <form @submit.prevent="submitForm">
    <div v-if="!auth" class="row">
      <input class="col" placeholder="Email" v-model="formInfo.email" type="text"></input>
      <input class="col" placeholder="Password" v-model="formInfo.password" type="password"></input>
      <button class="col" type="submit"  label="Log In"></button>
    </div>
    <div v-else class="row">
      Hello {{ firstname }}
    </div>
  </form>
</template>

<script>
  export default {
    data() {
      return {
        formInfo: {
          email: '',
          password: ''
        }
      };
    },
    methods: {
      submitForm() {
        this.$store.dispatch('login', {email: this.formInfo.email, password: this.formInfo.password})
        this.$store.dispatch('fetchUser')
      }
    },
    computed: {
      auth() {
        return this.$store.getters.isAuthenticated
      },
      firstname() {
        return this.$store.getters.user.firstname
      }    
    }
  }
  };
</script>

Ответы [ 2 ]

0 голосов
/ 03 марта 2020

Вы можете отправить действие из другого действия.

actions: {
  login({commit, dispatch}, authData) {
    axios.post("http://example.com/token/create/", {
        email: authData.email,
        password: authData.password
      })
      .then(res => {
        const accessToken = res.data.access;
        dispatch('fetchUser', accessToken);
        commit('authUser', { accessToken })
      })
  },
  fetchUser({commit, state}, accessToken) {
    axios.get("http://example.com/api/auth/v1/me/", {
      headers: {Authorization: "Bearer "  + accessToken}
    })
    .then(res => {
      commit('storeUser', res.data.user)
    })
  }
}
0 голосов
/ 03 марта 2020

вы пытались добавить await?

  async submitForm() {
    await this.$store.dispatch('login', {email: this.formInfo.email, password: this.formInfo.password});
    await this.$store.dispatch('fetchUser');
  }

, он будет ждать окончания входа в систему sh, прежде чем выбрать пользователя

, также возможно добавьте asyn c в ваш методы действий:

async login({commit}, authData) {...}

async fetchUser({commit, state}) {...}
...