我应该如何避免在平面vuex结构中重复的数据和API调用



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

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

用户状态模块

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

消息状态模块

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

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

// 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())
}
}

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

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

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

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

我还应该提到,我正在使用一个名为VuexFire的小助手库,它管理FirestorecollectionReference.onSnapshot()的绑定。这引入了另一个限制,即当添加、更新或删除文档时,我不能直接运行操作。这是因为VuexFire会自动处理所有这些更改,并且不支持挂接这些事件。相反,我必须循环浏览所有现有的消息并调用fetchUser()。我没有在上面的代码示例中包括这一点,因为它与snapshot.forEach()没有太大区别。如果需要的话,我也可以放弃这个图书馆。

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

从您键入的所有内容来看,防止fetchUser操作被不必要地调用似乎是至关重要的,所以我将重点关注您尝试过的一次尝试,以防止这种情况发生

我试图检查用户是否已经存在于用户数组中然后调用fetchUser((。然而,这不起作用,因为fetchUser是一个异步操作。它可能正在获取,因此检查用户是否已经在数组中通常测试错误

这个怎么样?

{
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)
}
})
},

相关内容

最新更新