0

我目前正在构建一个 vue/vuex/firestore/vuexFire 项目,我遇到了以下问题。

假设我想显示一个消息列表,其中每条消息都与一个用户相关联。一个用户可以提交多条消息,这些消息都将在他们的名下。在 vuex 中,它的平面表示可能如下所示:

用户状态模块

state: () => ({
  users: [
   {
    name: 'foo',
    id: 'bar'
   }
   //...
  ]
})

消息状态模块

state: () => ({
  messages: [
   {
    message: 'blah blah',
    authorId: 'bar'
   }
   //...
  ]
})

在服务器上(我使用的是 Firebase 的 Firestore),结构基本相同。因此,我获取所有消息,然后像这样关注每个 authorId:

// action in the vuex messages module
{
 fetchMessages: async ({ commit, dispatch }) => {
  
  const snapshot = await firestore.collection('messages').get();
  snapshot.forEach((doc) => {
   
   // commit the document
   commit('addMessage', doc.data())
   
   // fetch the associated user
   dispatch('fetchUser', doc.data().authorId)
  })
 },

 fetchUser: async ({commit}, id) => {
  const user = await firestore.collection('users').doc(id).get();
  commit('addUser', user.data())
 }

}

我遇到的问题是,如果有一个用户创建了多条消息,它们将一遍又一遍地添加到 users 数组中。此外,fetchUser()一遍又一遍地不必要地调用。到目前为止,我解决这个问题的尝试失败或不优雅:

  • users我试图在调用之前检查用户是否已经存在于数组中fetchUser()。但是,这不起作用,因为fetchUser是异步操作。它可能正在获取过程中,因此检查用户是否已经在数组中通常测试为假。

  • 我试图检查用户是否已经存在于addUser突变中。虽然这确实可以防止重复,但它并不能防止不必要的用户获取。此外,addUser突变必须在每次调用时检查用户不是重复的,这对于较大的数组可能会很昂贵。

  • 一种有效的方法是在状态中创建一个fetchJobs对象users。当fetchUser()被调用时,我将用户的 id 添加到对象中。然后,在获取其他用户之前,我会检查此对象以确保我没有获取重复项。与直接检查状态相反,这样做的原因是我在操作开始时提交了 fetchJob,因此它不是异步的。这样,其他组件和状态模块就可以访问它。但是,如果用户对象需要随时更新,这将不起作用,因为它仍将保留在 fetchJobs 对象中。

我还应该提到我正在使用一个名为 VuexFire 的小型帮助程序库,它管理 Firestore 的绑定collectionReference.onSnapshot()。这引入了另一个限制,即在添加、更新或删除文档时我无法直接运行操作。这是因为 VuexFire 会自动处理所有这些更改,并且不支持挂钩这些事件。相反,我必须遍历所有现有消息并调用fetchUser(). 我没有在上面的代码示例中包含它,因为它与snapshot.forEach(). 如果需要,我也可以放弃这个库。

那么,解决这个问题的最佳方法是什么?

4

1 回答 1

2

从您输入的所有内容来看,防止不必要地调用该操作似乎fetchUser是最重要的,因此我将专注于您尝试过的一次尝试,以防止这种情况发生

在调用 fetchUser() 之前,我尝试检查用户是否已经存在于用户数组中。但是,这不起作用,因为 fetchUser 是一个异步操作。它可能正在获取过程中,因此检查用户是否已经在数组中通常测试为 false

这个怎么样?

{
 fetchMessages: async ({ commit, dispatch }) => {
  
  const snapshot = await firestore.collection('messages').get();
  snapshot.forEach((doc) => {
   
   // commit the document
   commit('addMessage', doc.data())
   
   const userIndexInTheUsersStoreArray = store.state.users.findIndex(user => user.id === doc.data().authorId)
   
   const isUserInTheUsersStoreArray = userIndexInTheUsersStoreArray > -1
   
   if (!userInTheUsersStoreArray) {
    dispatch('fetchUser', doc.data().authorId)
   }
  })
 },

于 2020-08-05T10:34:46.977 回答