Search code examples
vue.jsasynchronousfetchvuex

Vuex - loading many tables - chain a bunch of await dispatch fetches?


I'm newish to Vue and hacking my way through loading a bunch of tables asynchronously.

Is there a more concise / efficient way of composing this?

initializeApp({ state, commit, dispatch }) {
  commit("initializeStore"); // sets userData from localStorage || ""
  if (state.userData.token) {
    dispatch("getTables");
  }
},
async getTables({ dispatch, commit }) {
  await dispatch("getCollections");
  const payload = await airtableQuery.getTableAsync("Merchants");
  commit("setMerchants", payload);
},
async getCollections({ dispatch, commit }) {
  await dispatch("getCategories");
  const payload = await airtableQuery.getTableAsync("Collections");
  commit("setCollections", payload);
},
async getCategories({ dispatch, commit }) {
  await dispatch("getSubLocations");
  const payload = await airtableQuery.getTableAsync("Categories");
  commit("setCategories", payload);
},
async getSubLocations({ dispatch, commit }) {
  await dispatch("getLocations");
  const payload = await airtableQuery.getTableAsync("SubLocations");
  commit("setSubLocations", payload);
},
async getLocations({ dispatch, commit }) {
  await dispatch("getQualities");
  const payload = await airtableQuery.getTableAsync("Locations");
  commit("setLocations", payload);
},
async getQualities({ dispatch, commit }) {
  await dispatch("getUserRoles");
  const payload = await airtableQuery.getTableAsync("Qualities");
  commit("setQualities", payload);
},
async getUserRoles({ dispatch, commit}) {
  await dispatch("getPreviousRoomScans");
  const payload = await airtableQuery.getTableAsync("User Roles");
  commit("setUserRoles", payload);
},
async getPreviousRoomScans({ commit }) {
  const payload = await airtableQuery.getTableAsync("Room Scans");
  commit("setPreviousRoomScans", payload);
},

Solution

  • Actions surely shouldn't chain each other like that, unless an action specifically depends on the result from previous action.

    initializeApp doesn't await for actions it dispatches, which prevents it from be chained correctly by a caller.

    For independent actions that should be dispatched on initialization, a common recipe is:

    initializeApp({ state, commit, dispatch }) {
      commit("initializeStore");
      if (state.userData.token) {
        await Promise.all([
          dispatch("getTables"),
          ...
        ]);
      }
    },
    async getTables({ commit }) {
      const payload = await airtableQuery.getTableAsync("Merchants");
      commit("setMerchants", payload);
    },
    ...