Vuex:根据已提取的数据使用axios提取数据

时间:2018-10-28 23:43:16

标签: javascript vue.js vuejs2 axios vuex

我正在通过Vuex存储区中的axios从外部API获取数据,这给了我一个包含对象的数组-假设-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");
},
  

获取所有城市后的静音

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)之前的调度之后,我还重构了获取详细信息的方式:

  1. 组件派发fetchCities
  2. fetchCities操作中:提交UPDATE_CITIES
  3. UPDATE_CITIES突变:在有效负载上映射.map并创建新对象->将所有内容推送到state.cities
  4. fetchCities操作中:为每个城市循环state.cities并调度fetchCityDetails(zipCode)
  5. fetchCityDetails操作中:提交UPDATE_CITY_DETAILS
  6. UPDATE_CITY_DETAILS突变中:在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;
}

问题仍然存在:是否有更好/更优化的方法来进行这种获取?

1 个答案:

答案 0 :(得分:2)

我认为,有很多更好,更优雅的方法来解决这个问题,而只是简单地帮助您解决错误(遍历可能是城市阵列的空数组)

修复

尝试将commit函数移至下一行。 arraycitiesRaw)为空,因为您在获取数据之前调用了该操作(因为axios.get是异步的)


替代解决方案

正如您所说,城市将显示在具有可扩展行的表格中,这些行用于显示城市详细信息。获取100-1000个城市的数据很多,但这仍然是后端的一个电话。但是,从性能和带宽(如果这是大数据使用的正确术语)的角度来看,遍历所有这些项目并对每个项目都进行请求可能会出现问题。

我个人会在用户实际需要此数据时处理每个请求。在您的情况下,只要用户单击一行以展开它即可。

将其存储在商店中吗?

何时要在商店中存储城市详细信息取决于您。您可以将其保留在组件中,但就我个人而言,我会将其用作某种缓存机制。

当用户单击一行时,检查详细信息是否已获取

if(!state.cityDetails[key]) {
    axios.get().then(res => {
    // Commit a mutation that saves the fetched details
    })
} else {
    // Use the 'cached' cityDetails
}

您的商店可能看起来像这样:

{
    cityDetails: {
        'keyCouldBeIdOrZipcode': {...},
        'anOtherAlreadyFetchedCity': {...}
    }
}

很抱歉输入错误和格式错误。在手机上输入代码太可怕了