【问题标题】:How to dispatch an action from within another action in another Vuex store module?如何从另一个 Vuex 商店模块的另一个动作中分派一个动作?
【发布时间】:2021-06-05 19:48:58
【问题描述】:

上下文

我有两个商店模块:“会议”和“需求”。 在商店“Demands”中我有“getDemands”动作,在商店“Meetings”中我有“getMeetings”动作。在访问 Firestore 中的会议数据之前,我需要知道需求的 ID(例如:需求 [i].id),因此“getDemands”操作必须在“getMeetings”被调度之前运行并完成。

Vuex 文档dispatching-action 非常完整,但我仍然不知道如何将其放入我的代码中。这里还有一些关于该主题的其他很好回答的问题:

我想知道实现我想要完成的任务的最佳方式。从我的角度来看,这可以通过触发另一个动作或使用异步/等待来完成,但我在实现它时遇到了麻烦。

dashboard.vue

  computed: {
    demands() {
      return this.$store.state.demands.demands;
    },
    meetings() {
      return this.$store.state.meetings.meetings;
    }
  },
  created() {
    this.$store.dispatch("demands/getDemands");
   
    //this.$store.dispatch("meetings/getMeetings"); Try A : Didn't work, seems like "getMeetings" must be called once "getDemands" is completed
  },

VUEX 商店 模块 A – requirements.js

export default {
  namespaced: true,
  state: {
    demands:[], //demands is an array of objects
  },
  actions: {

// Get demands from firestore     UPDATED

    async getDemands({ rootState, commit, dispatch }) {
      const { uid } = rootState.auth.user
      if (!uid) return Promise.reject('User is not logged in!')

      const userRef = db.collection('profiles').doc(uid)

      db.collection('demands')
        .where('toUser', "==", userRef)
        .get()
        .then(async snapshot => {
          const demands = await Promise.all(
            snapshot.docs.map(doc =>
              extractDataFromDemand({ id: doc.id, demand: doc.data() })
            )
          )
          commit('setDemands', { resource: 'demands', demands })
          console.log(demands)  //SECOND LOG
        })
      await dispatch("meetings/getMeetings", null, { root: true })    //UPDATE
    },

...

mutations: {
    setDemands(state, { resource, demands }) {
      state[resource] = demands
    },

...

模块 B – meeting.js


export default {
  namespaced: true,
  state: {
    meetings:[],
  },
  actions: {

// Get meeting from firestore    UPDATED

getMeetings({ rootState, commit }) {
      const { uid } = rootState.auth.user
      if (!uid) return Promise.reject('User is not logged in!')

      const userRef = db.collection('profiles').doc(uid)

      const meetings = []

      db.collection('demands')
        .where('toUser', "==", userRef)
        .get()
        .then(async snapshot => {
          await snapshot.forEach((document) => {
            document.ref.collection("meetings").get()
              .then(async snapshot => {
                await snapshot.forEach((document) => {
                  console.log(document.id, " => ", document.data())  //LOG 3, 4
                  meetings.push(document.data())
                })
              })
          })
        })
      console.log(meetings)    // FIRST LOG
      commit('setMeetings', { resource: 'meetings', meetings })
    },

...

mutations: {
    setMeetings(state, { resource, meetings }) {
      state[resource] = meetings
    },
...

【问题讨论】:

  • getDemands 收到数据并提交后,应该是return dispatch("meetings/getMeetings")。这样,使用dispatch('demands/getDemands') 它的.then() 实际上将在getMeetings 完成它正在做的任何事情之后发生。作为替代方案,您可以声明demands/getDemands async 并在调度getMeetings 之前使用await。这样返回demands 将等待getMeetings。附注:您不应该 return 来自操作的数据。您应该将其提交给state,组件将得到更新,因为它们使用状态数据。
  • getMeetings 中,for 循环有几个问题:(1)它在一次迭代后返回。您可能想为所有demands 运行正文,而不仅仅是第一个。如果正文是异步的,则需要使用Promise.all 来累积meetings。 (2)条件表达式有赋值,但应该是比较。
  • @tao @tony19 感谢您的帮助,我已尝试实现整体并删除数据返回,但是我仍然无法弄清楚如何确保在运行之前终止getDemands getMeetings。我更新了代码并添加了日志顺序。

标签: javascript vue.js google-cloud-firestore vuejs2 vuex


【解决方案1】:

语法:

dispatch(type: string, payload?: any, options?: Object): Promise<any

正确拨打电话

dispatch("meetings/getMeetings", null, {root:true})

【讨论】:

    猜你喜欢
    • 2018-04-18
    • 2016-12-23
    • 2018-02-01
    • 1970-01-01
    • 2020-08-27
    • 1970-01-01
    • 2020-12-11
    • 2017-07-25
    • 1970-01-01
    相关资源
    最近更新 更多