gpt4 book ai didi

vue.js - 使用 vuex 从 api 获取数据的最佳实践

转载 作者:搜寻专家 更新时间:2023-10-30 22:26:39 26 4
gpt4 key购买 nike

有两个页面(或者,关于 vue 术语的组件)都需要相同的数据集,这些数据是通过 http 上的 api 提供的。访问这两个组件的顺序是未定义的(或者,取决于用户行为)并且数据应该只获取一次,因为它不会改变很多。

我知道 state 存储实际数据,mutation 改变 stateactions 做异步请求、多突变协调等肮脏的工作。

问题是:执行上述某些缓存逻辑的最佳做法是什么?

我想出了以下三种方法,但对我来说没有一种是完美的:

缺点:

  1. 我需要在访问任何地方的数据之前分派(dispatch)操作,因为我不知道数据是否已经被提取。

    // ComponentA
    async mouted () {
    await this.store.dispatch('fetchData')
    this.someData = this.store.state.someData
    }

    // ComponentB
    async mouted () {
    await this.store.dispatch('fetchData')
    this.someData = this.store.state.someData
    }

    // vuex action
    {
    async fetchData ({ state, commit }) {
    // handles the cache logic here
    if (state.someData) return
    commit('setData', await apis.fetchData())
    }
    }
  2. 缓存逻辑散布在整个代码库中——臭~

    // ComponentA
    async mouted () {
    if (this.store.state.someData === undefined) {
    // handles the cache logic
    await this.store.dispatch('fetchData')
    }
    this.someData = this.store.state.someData
    }

    // ComponentB
    async mouted () {
    if (this.store.state.someData === undefined) {
    // handles the cache logic
    await this.store.dispatch('fetchData')
    }
    this.someData = this.store.state.someData
    }

    // vuex action
    {
    async fetchData ({ state, commit }) {
    commit('setData', await apis.fetchData())
    }
    }
  3. 可能是这三者中最完美的,但是我觉得用action dispatch的返回值作为数据有点奇怪。随着存储的增长,缓存逻辑将分散在所有操作中(会有越来越多的操作重复相同的缓存逻辑)

    // ComponentA
    async mouted () {
    this.someData = await this.store.dispatch('fetchData')
    }

    // ComponentB
    async mouted () {
    this.someData = await this.store.dispatch('fetchData')
    }

    // vuex action
    {
    async fetchData ({ state, commit }) {
    if (!state.someData) commit('setData', await apis.fetchData())
    return state.someData
    }
    }

我更喜欢将缓存逻辑放入我的“vue&vuex-independent”网络层。但是网络层的“缓存”部分可能会变成另一个“vuex”存储。 XD

最佳答案

我觉得我正在重新发明轮子,应该有更好的现成的东西来做到这一点,但这是我的轮子,它对我来说滚动得很好。

我回复是为了回馈,但也因为我希望有人能告诉我更好的方法!

我的方法通过使用“加载” promise 而不是简单地检查特定状态是否已加载来解决避免多次提取的问题。如果您的 api 很慢和/或您的组件可能会在呈现之前多次调用获取操作,这将帮助您将它保持为单个 api 调用。

  // vuex action
async fetchCustomers({commit, state}) {
await loadOrWait(loadingPromises, 'customers', async () => {
// this function is called exactly once
const response = await api.get('customers');
commit('SET_CUSTOMERS', {customers : response.data });
});
return state.customers;
},

loaded 只是一个对象,它存储了每次获取的 promise 。我看过someone改用弱映射(如果内存使用是一个问题,那将是一个不错的选择)

  const loadingPromises = { 
customers: false,
customer: { }
}

loadOrWait 是一个简单的实用程序函数,它要么执行(恰好一次)一个函数(例如,您从 api 中提取)要么它看到提取正在进行中,所以它返回上一个 fetch 调用的 promise 。在任何一种情况下,您都会得到一个 promise ,该 promise 将解析为 API 调用的结果。

async function loadOrWait(loadingPromises, id, fetchFunction) {
if (!loadingPromises[id]) {
loadingPromises[id] = fetchFunction();
}
await loadingPromises[id];
}

也许您想要更细化您的抓取,例如,如果尚未抓取特定客户,则抓取他们。

  // vuex action 
async fetchCustomer({commit, state}, customerId) {
await loadOrWait(loadingPromises.customer, customerId, async () => {
const response = await api.get(`customers/${customerId}`);
commit('SET_CUSTOMER', { customerId, customer: response.data });
});
return state.customer[customerId];
},

一些其他想法:

  • 也许你不想永远缓存结果,在这种情况下你可以在 loadOrWait 中发挥创意,例如,像这样
setTimeout(()=>loadingPromises[id]=false,60*1000)
  • 也许您想定期刷新/轮询数据。让 loadOrWait 保存函数也很简单!当您执行它们时,它会更新状态,如果您是一名优秀的 vue 编码员,您的应用程序将会刷新。
const fetchFunctionMap = {};

async function loadOrWait(loadingPromises, id, fetchFunction) {
if (!loadingPromises[id]) {
loadingPromises[id] = fetchFunction();
// save the fetch for later
fetchFunctionMap[id] = fn;
}
await loadingPromises[id];
}

async function reload(loadingPromises, id) {
if (fetchFunctionMap[id]){
loadingPromises[id] = fetchFunctionMap[id]();
}
return await loadingPromises[id];
// strictly speaking there is no need to use async/await in here.
}

//reload the customers every 5 mins
setInterval(()=>reload(loadingPromises,'customers'), 1000 * 60 * 5);

关于vue.js - 使用 vuex 从 api 获取数据的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51121690/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com