我在 Vuex 存储中通过 axios 从外部 API 获取数据,这为我提供了一个包含对象的数组 - 比方说 - cities
。
每个 city
都有一个 zipCode
,我需要用它来获取城市详细信息。
我想将该详细信息对象作为新键添加到 cities
数组。
现在我正在获取所有城市,并有另一个 Vuex 操作来获取城市详细信息。
ACTION to fetch all cities
fetchCities: ({ commit, state, dispatch }) => {
let baseUrl = "https://my-url/cities";
let config = {
headers: {
accept: "application/json",
Authorization: ...
},
params: {
param1: "a",
param2: "b"
}
};
axios
.get(baseUrl, config)
.then(function(response) {
commit("UPDATE_CITIES_RAW", response.data.items);
})
.catch(function(error) {
console.log(error);
});
dispatch("fetchCityDetails");
},
MUTATION after fetching all cities
UPDATE_CITIES_RAW: (state, payload) => {
state.citiesRaw = payload;
},
该数组中的每个对象都有一个 zipCode
,我正在使用它获取有关该城市的详细信息。
我尝试在操作中循环 citiesRaw
数组以获取详细信息并为每次迭代提交更改,但此时状态数组为空 ,因为操作在突变之前被调用。
ACTION to fetch city details
fetchCityDetails: ({ commit, state }) => {
let baseUrl = "https://my-url/cities/"
let config = {
headers: {
accept: "application/json",
Authorization: ...
}
};
// citiesRaw is empty at this point
state.citiesRaw.forEach(e => {
let url = baseUrl + e.zipCode;
axios
.get(url, config)
.then(function(response) {
commit("UPDATE_CITY_DETAILS", {
response: response.data,
zipCode: e.zipCode
});
})
.catch(function(error) {
console.log(error);
});
});
},
等待第一次获取然后更新数组的最佳方法是什么?
我是应该使用同一个数组还是创建一个新数组?
或者是否有更好的方法来基于 Vuex 存储中获取的数据进行获取?
UPDATE
在异步函数完成之前修复调度之后(感谢@Y-Gherbi),我还重构了获取细节的方式:
- 组件调度
fetchCities
- 在
fetchCities
操作中:提交UPDATE_CITIES
- 在
UPDATE_CITIES
突变中:.map 负载并创建新对象 -> 将所有内容推送到state.cities
- 在
fetchCities
操作中:循环state.cities
并为每个城市分派(dispatch)fetchCityDetails(zipCode)
- 在
fetchCityDetails
操作中:提交UPDATE_CITY_DETAILS
- 在
UPDATE_CITY_DETAILS
突变中:在state.cities
上映射并将cityDetails
对象添加到引用的城市对象
new actions
fetchCities: ({ commit, state, dispatch }) => {
let baseUrl = "https://my-url/cities";
let config = {
headers: {
accept: "application/json",
Authorization: ...
},
params: {
param1: "a",
param2: "b"
}
};
let url = baseUrl;
axios
.get(url, config)
.then(function(response) {
commit("UPDATE_CITIES", response.data.items);
state.cities.forEach(city => {
dispatch("fetchCityDetails", city.zipCode);
});
}
})
.catch(function(error) {
console.log(error);
});
},
fetchCityDetails: ({ commit }, zipCode) => {
let baseUrl = "https://my-url/cities";
let config = {
headers: {
accept: "application/json",
Authorization: ...
},
};
let url = baseUrl + "/" + zipCode;
axios
.get(url, config)
.then(function(response) {
commit("UPDATE_CITY_DETAILS", {
cityDetails: response.data,
zipCode: zipCode
});
})
.catch(function(error) {
console.log(error);
});
}
new mutations
UPDATE_CITIES: (state, cities) => {
// I don't need all data & I want to rename the keys from the response,
// so I create a new object
cities = cities.map(city => {
let obj = {};
obj.zipCode = city.zip_code
obj.key1 = city.key_1;
obj.key2 = city.key_2;
return obj;
});
state.cities.push(...cities);
},
UPDATE_CITY_DETAILS: (state, payload) => {
let cities = state.cities;
// add one details-object for each city
cities = cities.map(city => {
if (city.zipCode == payload.zipCode) {
city.cityDetails = payload.cityDetails;
}
return city;
});
state.cities = cities;
}
问题仍然存在:对于这种抓取是否有更好/更优化的方法?
最佳答案
我认为有更好、更优雅的方法来处理这个问题,但只是为了帮助您解决这个错误(循环一个空数组,该数组应该是一个城市数组)
修复
尝试将调度函数移动到提交函数之后的下一行。 array
(citiesRaw
) 是空的,因为您在获取数据之前调用操作(因为 axios.get
是异步操作)
替代方案
如您所说,城市显示在具有可扩展行的表格中,用于显示城市详细信息。获取 100-1000 个城市是相当多的数据,但它仍然是对后端的一次调用。但是,从性能和带宽(如果这是大数据使用的正确术语)的 Angular 来看,遍历所有这些项目并为每个项目发出请求可能会出现问题。
就个人而言,只要用户实际需要此数据,我就会处理每个请求。在您的情况下,每当用户单击一行以将其展开时。
存放在商店里?
何时要在商店中存储城市详细信息由您决定。您可以将它保留在组件中,但就我个人而言,我会将其用作某种缓存机制。
当用户点击一行时,检查是否已经获取了详细信息
if(!state.cityDetails[key]) {
axios.get()
.then(res => {
// Commit a mutation that saves the fetched details
})
.catch((error) => {
// Handle error
})
} else {
// Use the 'cached' cityDetails
}
您的商店可能看起来像这样:
{
cityDetails: {
keyCouldBeIdOrZipcode: {...},
anOtherAlreadyFetchedCity: {...},
}
}
对于错别字和错误的格式,我们深表歉意。在手机上输入代码太可怕了
关于javascript - Vuex:根据已获取的数据使用 axios 获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53037066/