Я извлекаю данные из внешнего API через axios в хранилище Vuex, которое дает мне массив с объектами - скажем, cities
.
Каждый city
имеет zipCode
,с которой мне нужно получить детали города.Я хочу добавить этот подробный объект в качестве нового ключа в массив cities
.
Сейчас я выбираю все города и выполняю еще одно действие Vuex для получения сведений о городе.
ДЕЙСТВИЕ для извлечения всех городов
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 после извлечения всех городов
UPDATE_CITIES_RAW: (state, payload) => {
state.citiesRaw = payload;
},
Каждый объект в этом массиве имеет zipCode
, с помощью которого я извлекаю подробности об этом городе.
Я попытался зациклить массив citiesRaw
внутри действия, чтобы извлечь детали и зафиксировать изменение для каждой итерации, , но массив изсостояние пусто в этот момент , потому что действие вызывается до мутации.
ДЕЙСТВИЕ для получения сведений о городе
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?
ОБНОВЛЕНИЕ
После исправления диспетчеризации еще до завершения асинхронной функции (спасибо, @ Y-Gherbi) я также реорганизовал способ извлечения деталей:
- Отправка компонентов
fetchCities
- in
fetchCities
action: commit UPDATE_CITIES
- in
UPDATE_CITIES
mutation: .map в полезной нагрузке и создание нового объекта -> подтолкнуть все к state.cities
- in
fetchCities
action: loop state.cities
& dispatch fetchCityDetails(zipCode)
для каждого города - in
fetchCityDetails
action: commit UPDATE_CITY_DETAILS
- in
UPDATE_CITY_DETAILS
мутация: .map on state.cities
и добавьте cityDetails
объект к указанному городскому объекту
новые действия
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);
});
}
новые мутации
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;
}
Остается вопрос: есть ли лучший / более оптимизированный подход к такому извлечению?