0

Имеется следующий код. При инициализации приложения я получаю массив объектов с информацией по прокси. Запуск 1 диспетчера дает мне массив из 100 объектов.

Во 2 действии getCountryList я хочу обработать данный массив из 100 объектов и получить новый массив из которого я буду получать в дальнейшем список стран и сколько всего прокси по странам.

По факту получается, что во время выполнения 2 действия, на обработку я получаю пустую строку. Я так понимаю, что эти процессы как-то идут парралельно, в итоге 1 действие еще не успело вызвать мутацию и свормировать нужное состояние (массив из 100 объектов) и уже вызывается 2-е... в итоге я получаю пустое значение во 2 действии.

Как мне выстроить цепочку вызовов, т.е. 2 действие вызывается, только после того, как завершится 1-е действие?

У меня есть подозрение, что можно все либо одним действием сделать, либо использовать промисы. Подскажите как реализовать такой момент

EDIT: как и подозревал экшены асинхронные, поэтому не работает как надо.

Теперь вопрос, как организовать что-то подобное, но без сетТаймаута, чтобы 2 dispatch запускался после 1-го, иначе setTimeout в любой момент может подвести

created() {
this.$store.dispatch("getProxyList"); 
setTimeout(() => this.$store.dispatch("getCountryList"), 1000);
},

//Инициализация App.vue

created() { this.$store.dispatch("getProxyList"); this.$store.dispatch("getCountryList");
},

//Хранилище

const state = { listProxy: "", countries: "", proxyInfo: {}, proxyCountry: [], proxyCountryCounter: 0 };

const mutations = { UPDATE_LIST_PROXY(state, payload) { state.listProxy = payload; }, UPDATE_LIST_COUNTRY(state, payload) { state.countries = payload; }, UPDATE_PROXY_INFO(state, payload) { state.proxyInfo = payload; }, UPDATE_PROXY_COUNTRY(state, payload) { state.proxyCountry = payload; }, UPDATE_PROXY_COUNTRY_COUNTER(state, payload) { state.proxyCountry = payload; }, };

const actions = { getProxyList({ commit }) { axios .get("proxy.json") .then(response => { commit("UPDATE_LIST_PROXY", response.data); // здесь я формирую state.listProxy }); }, getCountryList({ commit }) { // .get("https://proxyfordevelopers.com/api/proxies/?format=json") //TODO: Убрать лишний запрос. Данные можно получать из общего списка прокси console.log(state.listProxy) // Вот здесь по идее мне нужен listProxy, чтобы разобрать его на другой массив, а по факту получаю пустое состояние let countryObj = {}; let proxyList = state.listProxy;

    for (let i = 0; i < proxyList.length; i++) {
      let key = proxyList[i].country;
      countryObj[key] = (countryObj[key] === undefined) ? 1 : countryObj[key] + 1;
    }

    let countryArr = [];

    for (var key in countryObj) {
      countryArr.push({
        name: key,
        count: countryObj[key]
      })
    }
    commit("UPDATE_LIST_COUNTRY", countryArr);

}, setProxyInfo({ commit }, id) { let proxyList = state.listProxy;

let currentProxyInfo = proxyList.find(item => item.id === id);
commit("UPDATE_PROXY_INFO", currentProxyInfo);

}, setCountryPhoxy({commit}, country) { let listCountryProxy = state.listProxy.filter(item => item.country === country) commit("UPDATE_PROXY_COUNTRY", listCountryProxy); },
};

const getters = { listProxy: state => state.listProxy, countries: state => state.countries, proxyInfo: state => state.proxyInfo, proxyCountry: state => state.proxyCountry, proxyCountryCounter: state => state.proxyCountry.length

};

//--------

shub1nk
  • 133
  • я вообще не пойму, что мешает сделать все в getProxyList? – Paul Wall Sep 10 '18 at 18:01
  • Был такой вариант и это первое что пришло в голову. Хотел сохранить логическое разделение экшенов, подумал что есть вариант при инициализации просто цепочку вызовов сформировать, чтобы хранилище не ломать. Возможно ли вообще такое и правильно ли я мыслю в стороны Промисов? – shub1nk Sep 10 '18 at 18:04
  • меня больше интересует что за commit, откуда он? что он делает. Просто при вызове this.state.listProxy логично что пусто, тк ничего же там не определено – Paul Wall Sep 10 '18 at 18:07
  • commit так в документации и в книге смотрел https://vuex.vuejs.org/ru/guide/mutations.html. Разместил в коде весь листинг хранилища – shub1nk Sep 10 '18 at 18:16
  • console log на this.listProxy что нибудь показывает? – Paul Wall Sep 10 '18 at 18:19
  • this.listProxy => undefined//// state.listProxy => вообще пустота – shub1nk Sep 10 '18 at 18:22
  • тут именно надо одно действие вызвать после другого ну или в 1 действии сразу 2 нужных мутации вызывать – shub1nk Sep 10 '18 at 18:24

2 Answers2

2
created () {
  this.$store.dispatch("getProxyList").then(() => {
    this.$store.dispatch("getCountryList");
  });
},

  // нужно вернуть промис(запрос к серверу через axios)
  getProxyList({ commit }) {
    return axios
    .get("proxy.json")
      .then(response => {
        commit("UPDATE_LIST_PROXY", response.data); // здесь я формирую state.listProxy
      });
  },

Если не сработает, то добавьте еще

commit("UPDATE_LIST_PROXY", response.data);
// вот это
return response.data
  • Сработало. Вот где собака зарыта была. Получается чтобы then сработал, вернуть надо что-то, а я ничего не возвращал. В документации по Vuex https://vuex.vuejs.org/ru/guide/actions.html , кстати, это описано, но я видимо сути не понял. Надо с промисами будет поразбираться как следует. – shub1nk Sep 12 '18 at 04:49
  • Вот хорошая статья по промисам. Суть в том что вызываемое действие оборачивается в new Promise, если ничего не вернуть, то оно возвращает resolve(undefined). В коде выше я возвращаю результат then, then всегда возвращает промис, то есть чтобы добавить что надо делать после запроса к api и после того как вы сделали commit надо продолжить цепочку then промисов, а для этого ее надо вернуть. Я сам когда это писал немного запутался, не такая это и легкая тема)) – Илья Зелень Sep 12 '18 at 05:16
  • Спасибо. Видел эту статью, но сразу не понял, буду пробовать еще заход делать, в любом случае разобраться необходимо) – shub1nk Sep 12 '18 at 06:22
1

Действия в vuex это промисы, они всегда асинхронные, поэтому мождо дождаться результата используя then.

created () {
  this.$store.dispatch('getProxyList').then(result => {
    // в result записан результат выполнения getProxyList
    this.$store.dispatch('getCountryList')
  });
},

Советую также использовать async/await вместо then если он у Вас настроен:

async created () {
  const result = await this.$store.dispatch('getProxyList')
  await this.$store.dispatch('getCountryList')
},
  • async/await - не настроент then тоже пробовал, только без result - у меня было так () => {...} только у меня почему-то даже с такой конструкцией при вызове консоль.лога во 2 действии state.proxyList пустой. – shub1nk Sep 12 '18 at 03:44
  • result вообще undefined получается – shub1nk Sep 12 '18 at 04:16
  • getProxyList у вас ничего не возвращает, это я для примера показал как с действий можно возвращать результат. У вас не работает какое-то действие как Вам нужно? – Илья Зелень Sep 12 '18 at 04:31
  • Получается такая ситуация. При инициализации во 2 действие передается пустое значение , соответственно данных нет при рендеринге и в хранилище тоже пустое состояние. Но если я поменяю что-то в коде, даже коммент просто напишу, запускается горячая перезагрузка модуля и данные уже появляются. Т.е. все работает по сути, но начальном этапе есть проблема – shub1nk Sep 12 '18 at 04:32
  • Суть этих действий: 1-м действием сделать ajax-запрос, получить массив объектов и записать этот массив в состояние listProxy – shub1nk Sep 12 '18 at 04:38
  • 2 действие: взять результат 1-го действия провести с ним манипуляции и записать данные в другое состояние - countries – shub1nk Sep 12 '18 at 04:39
  • я так по коду и понял, проверьте мой новый ответ – Илья Зелень Sep 12 '18 at 04:40