【问题标题】:How to write Vuex mutation without asynchronous promise如何在没有异步承诺的情况下编写 Vuex 变异
【发布时间】:2019-11-26 18:20:36
【问题描述】:

我正在使用 Vue.js、Vuex 和 Firebase 构建应用程序。在这个应用程序中,来自 Firestore 数据库的数据被更新为突变状态。当前形式的应用程序似乎可以正常工作,因为状态随后通过 getters 方法返回到模板。但是,据我了解,突变是同步的,而 Promise (.then) 是异步的。因此, .then 承诺不应该在突变内部。那么为什么这个应用程序仍然可以正常执行呢?重新配置突变以使 FB 数据在没有承诺的情况下更新到状态的最佳方法是什么?或者甚至有必要改变这一点?这是我的 Vuex 代码。谢谢!

import Vue from 'vue'
import Vuex from 'vuex'
import firebase from 'firebase'
import db from '@/firebase/init'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    items: null
  },
  getters: {
    getItems: state => {
      return state.items
    }
  },
  mutations: {
    setAllUser: state => {
      const items = []
      db.collection('users').get()
      .then(snapshot => {
        snapshot.forEach(doc => {
          let userData = doc.data()
          userData.id = doc.id
          items.push(userData)
        })
        state.items = items
      })
    },
  actions: {
    setAllUser: context => {
      context.commit('setAllUser')
    }
  }
})


**SOLUTION**

import Vue from 'vue'
import Vuex from 'vuex'
import firebase from 'firebase';
import db from '@/firebase/init'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    items: null
  },
  getters: {
    getItems: state => {
      return state.items
    }
  },
  mutations: {
    setAllUser: (state, items) => {
      state.items = items
    }
  },
  actions: {
    setAllUser: async context => {
      let snapshot = await db.collection('users').get();
      const items =[]
      snapshot.forEach(doc => {
        let userData = doc.data()
        userData.id = doc.id
        items.push(userData)
      })
      context.commit('setAllUser', items)
    }
  }
})

【问题讨论】:

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


    【解决方案1】:

    将您的异步代码移动到操作中:

    {
      mutations: {
        setAllUser: (state, items) => state.items = items
      },
      actions: {
        setAllUser: async context => {
          let snapshot = await db.collection('users').get();
          let items = snapshot.map(doc => {
            let userData = doc.data();
            userData.id = doc.id
            return userData;
          });
          context.commit('setAllUser', items)
        }
    }
    

    那么问题是为什么?

    • 单一职责:您的变更应该只负责设置状态。
    • 不确定 vue-devtools 会如何反应,我猜它只会显示一个突变。
    • 您的变更应仅取决于负载和状态,而不取决于网络/服务器响应等
    • 您的同事不会想到会发生这种情况

    为什么有效?

    • 与直接从 devtools 执行此操作的原因相同:window.store.state.items = []。 Vuex 只是覆盖 getter 并更新状态会触发更新 dom。

    附:您可以在操作中使用promise.then 而不是await

    【讨论】:

    • 这似乎是有道理的,因为动作是同步的。但是,我现在收到一个新错误,上面写着“snapshot.map 不是函数”。我该如何解决这个问题?谢谢!
    • 好的,所以在对您的答案进行一些额外修改后,我能够使其工作。解决方案发布在初始代码下方。非常感谢你让我走上正轨! Async 和 await 关键字(用于异步操作)有效!
    猜你喜欢
    • 2019-12-16
    • 1970-01-01
    • 2017-12-05
    • 2021-08-10
    • 2019-05-25
    • 1970-01-01
    • 2017-03-05
    • 2019-08-16
    • 2021-04-28
    相关资源
    最近更新 更多