vuex를 사용하여 API에서 데이터를 가져오는 모범 사례
두 페이지(또는 vue의 용어에 관한 컴포넌트)가 있으며 둘 다 동일한 데이터 세트를 필요로 하며 api over http를 통해 제공됩니다.이러한 2개의 컴포넌트가 표시되는 순서는 정의되어 있지 않습니다(또는 사용자 동작에 의존합니다).데이터는 크게 변경되지 않기 때문에1회만 취득해야 합니다.
나는 ...라는 생각을 알고 있다.state
실제 데이터를 저장합니다.mutation
변이하다state
,그리고.action
는 비동기 요구, 멀티태스킹 조정 등의 더러운 작업을 수행합니다.
문제는 다음과 같습니다.위에서 설명한 바와 같이 캐싱 로직을 수행하기 위한 베스트 프랙티스는 무엇입니까?
나는 다음의 세 가지 방법을 생각해 냈지만, 어느 것도 나에게 완벽해 보이지 않는다.
단점:
데이터가 이미 Import되었는지 알 수 없기 때문에 모든 장소에서 데이터에 액세스하기 전에 작업을 디스패치해야 합니다.
// 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()) } }
캐싱 로직이 코드베이스 곳곳에 흩어져 있어 냄새나~
// 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()) } }
아마 이 세 가지 중에서 가장 현적인 모습일 것입니다만, 액션 디스패치의 리턴치를 데이터로 하는 것은 조금 이상하다고 생각합니다.캐싱 로직은 스토어가 커짐에 따라 액션 전체에 분산됩니다(같은 캐싱 로직을 반복하는 액션이 점점 많아집니다).
// 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' 네트워크 계층에 넣는 것을 선호합니다.그러나 네트워크 계층의 '캐시' 부분은 또 다른 'vux' 저장소가 될 수 있습니다.XD
나도 최근에 비슷한 문제에 봉착했다.그리고 네 행동 속에서 최선을 다하는 게 최선이라는 걸 깨달았어이 기능은, 「」를 계속하는 데 도움이 됩니다.vuex
라이프 사이클에 대응합니다.따라서 코드는 다음과 같습니다.
{
async fetchData ({ state, commit }) {
if (!state.someData) commit('setData', await apis.fetchData())
commit('setData', state.someData)
}
}
그 후 사용getters
함께 일하다state.someData
컴포넌트를 할당하지 않고 컴포넌트에 저장합니다.
바퀴를 재발명하고 있는 것 같고, 이것을 할 수 있는 기성품이 있을 것 같습니다만, 여기 바퀴가 있고, 저는 잘 굴러갑니다.
돌려주려고 답장하는 건데, 더 좋은 방법을 알려줬으면 좋겠어!
내 접근 방식은 단순히 특정 상태가 로드되었는지 확인하는 대신 '로드' 약속을 사용하여 여러 개의 페치를 회피하는 문제를 해결합니다.api가 느리거나 컴포넌트가 렌더링 전에 여러 번 fetch 액션을 호출할 수 있는 경우 단일 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는 모든 취득에 대한 약속을 저장하는 오브젝트입니다.대신 약한 맵을 사용하는 것을 본 적이 있습니다(메모리 사용이 우려된다면 좋은 선택입니다).
const loadingPromises = {
customers: false,
customer: { }
}
loadOrWait
는 함수를 실행(예를 들어 api로부터의 페치)하거나 페치가 진행 중임을 인식하여 이전 페치콜의 약속을 반환하는 단순한 유틸리티 함수입니다.어느 경우든 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 coder가 되어 있으면 어플리케이션이 갱신됩니다.
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);
제가 여기 늦게 온 건 알지만, 제 접근 방식이 이 문제에 대한 잠재적인 해결책을 제시해 주길 바랍니다.이 접근방식은 실제로 많은 프로젝트에서 사용해 온 것으로, 매우 효과적이고 알기 쉽다는 것을 알게 되었습니다.
으로 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.API factory/service
Vuex action
데이터를 얻을 때마다 API 팩토리에서 공개되는 서비스를 호출합니다.이 서비스는 필요한 데이터가 이미 저장소에 있는지 확인하고, 그렇지 않으면 API에서 데이터를 가져옵니다.
그건 이런 식이다:
// Vuex store
const store = new Vuex.Store({
state: {
someData: {}
},
mutations: {
SET_SOME_DATA (state, payload) {
state.someData = payload
}
}
})
// API factory/service
import store from 'yourStoreDirectory'
export async getSomeData() {
if (store.state.someData !== undefined) {
return store.state.someData
}
try {
// fetch API
// store data into Vuex for next time
store.commit('SET_SOME_DATA', response)
} catch (err) {
// handle errors
}
}
// Component
import { getSomeData } from 'yourAPIFactoryDirectory'
export default {
async mounted () {
this.someData = await getSomeData()
}
}
getSomeData
이 서비스는 스토어에서 가져온 것인지 API에서 가져온 것인지 고민하지 않아도 됩니다.이렇게 하면 코드가 더 깨끗하고 읽기 쉬워집니다.
으로 안 action
그리고 으로 저는 제 ㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇ를 가지고 . 그리고 일반적으로 저는 항상 제 마음을 지키려고 노력합니다.Vuex
데이터 처리나 비즈니스 로직 관리가 아닌 상태 관리라는 제목과 마찬가지로 최대한 단순합니다.이 아이디어에 대한 자세한 내용은 이 문서를 참조하십시오.https://javascript.plainenglish.io/stop-using-actions-in-vuex-a14e23a7b0e6
언급URL : https://stackoverflow.com/questions/51121690/best-practice-for-fetching-data-from-api-using-vuex
'source' 카테고리의 다른 글
왜 Double일까요?음수가 아닌 MIN_VALUE (0) | 2022.08.16 |
---|---|
Vue js 2를 사용하여 구성 요소 하위 구성 요소 체인에서 이벤트를 버블링하려면 어떻게 해야 합니까? (0) | 2022.08.16 |
Java에서 BigDecimal 변수 == 0인지 확인하는 방법 (0) | 2022.08.16 |
루프 내에는 현재 루프되어 있는 일치를 취득하여 특정 이름의 참가자를 반환하는 함수가 있습니다.중복을 방지하는 방법 (0) | 2022.08.16 |
긴 인쇄 방법 (0) | 2022.08.16 |