Дебюссировать Vuex Action Call к базе данных не работает - PullRequest
0 голосов
/ 08 января 2020

У меня есть несколько компонентов, которые могут быть отдельными или на одной странице. Каждый из этих компонентов использует одно и то же состояние Vuex . Поскольку каждый из них может использоваться на других страницах и все еще работать, каждый из них отправляет вызов тому же Vuex действию , которое, в свою очередь, вызывает службу, которая использует ax ios для получения данных JSON.

Все это прекрасно работает!

Однако, когда у меня есть 2 (или более) этих компонентов на одной странице, это ax ios вызов вызывается 1 раз для каждого из компонентов. Первоначально я пошел по пути, пытаясь увидеть, существуют ли данные, и создал метку времени «последние полученные данные в», чтобы я мог просто обойти второй вызов. Однако это происходит как для события created компонентов, так и по существу вызывается одновременно.

Итак, введите debounce. Похоже, точная причина этого. Однако, когда я его реализую, он терпит неудачу и переходит к следующей строке кода, а не awaiting. Что я делаю не так?

Компонент повестки дня (тот, который использует то же состояние)

async created() {
  await this.gatherCalendarData();
},
methods: {
  async gatherCalendarData() {
    await this.$store.dispatch('time/dateSelected', this.$store.state.time.selectedDate);
  },
},

Компонент месяца (другой, обратите внимание, что они одинаковы)

async created() {
  await this.gatherCalendarData();
},
methods: {
  async gatherCalendarData() {
    await this.$store.dispatch('time/dateSelected', this.$store.state.time.selectedDate);
  },
},

Действие вызывается

async dateSelected(context, data) {
  let result = await getCalendarData(isBetween.date, context.rootState.userId);
  await context.commit('SET_MONTHLY_DATA', { result: result.Result, basedOn: isBetween.date });
},

Этот метод getCalendarData находится в служебном файле, который я создал для выполнения вызовов API (ниже).

Это ошибка, которую я получаю (один раз для каждый компонент), который вызывает это действие.

[Vue warn]: Error in created hook (Promise/async): "TypeError: Cannot read property 'Result' of undefined"

, что относится к 3-й строке выше: result: result.Result

Служба API

const getCalendarData = debounce(async (givenDate, userId) => {
  let response = await getCalendarDataDebounced(givenDate, userId);
  return response;
}, 100);

const getCalendarDataDebounced = async (givenDate, userId) => {
  let result = await axiosGet('/api/v2/ProjectTime/BuildAndFillCalendarSQL', {
    givenDate: givenDate,
    userID: userId,
  });

  return result;
};

Ax ios Wrapper

const axiosGet = async (fullUrl, params) => {
  let result = null;

  try {
    let response = await axios.get(fullUrl, params ? { params: params } : null);
    result = await response.data;
  } catch(error) {
    console.error('error:', error);
  }

  return result;
};

Если я помещаю console.log сообщения до, после и внутри вызова getCalendarData, а также в методы getCaledarDataDebounced: (при условии, что на страница) отображаются журналы 2 до и затем появляются журналы 2 после. Затем регистрируется ошибка, упомянутая выше для каждого из 2 компонентов, затем регистрируется одно «внутри getCalendarData» и, наконец, журнал из дебазованной версии, куда он на самом деле получает данные.

Так что похоже Десиманс работает в том, что он запускается только один раз. Но похоже, что await вызов let result = await getCalendarData(isBetween.date, context.rootState.userId); не является действительно Ожиданием.

Я что-то здесь упускаю?

РЕДАКТИРУЕТСЯ после ответа

Основано на ответе @JakeHamTexas, мой action из dateSelected теперь (фактический полный код, ничего не удалено, как указано выше, чтобы ничего не путать):

async dateSelected(context, data) {
  console.log('dateSelected action');
  let isBetween = isDateWithinCurrentMonth(data, context.state);

  if (!isBetween.result) {
    // The date selected is in a different month, so grab that months data
    return new Promise(resolve => {
      getCalendarData(isBetween.date, context.rootState.userId)
        .then(result => {
          console.log('inside promise');
          context.commit('SET_MONTHLY_DATA', { result: result.Result, basedOn: isBetween.date });
          context.commit('SET_SELECTED_DATE', isBetween.date);
          context.commit('statistics/TIME_ENTRIES_ALTERED', true, { root: true });
          resolve();
        });
    });
  } else {
    // The date selected is within the given month, so simply select it
    context.commit('SET_SELECTED_DATE', data);
  }

  context.commit('CLEAR_SELECTED_TIME_ENTRY_ID');
},

И мой вызов API getCalendarData теперь:

const getCalendarData = async (givenDate, userId) => {
  console.log('getting calendar data');
  let result = await axiosGet('/api/v2/ProjectTime/BuildAndFillCalendarSQL', {
    givenDate: givenDate,
    userID: userId,
  });

  return result;
};

Ошибка ушла! Однако, это не похоже на debouncing - то есть все вызывается 3 раза. Я ожидаю, что dateSelected action будет вызван 3 раза. Но я бы хотел, чтобы getting calendar data не вызывали 3 раза. Если это помогает, вот как выглядит консоль:

dateSelected action
getting calendar data
dateSelected action
getting calendar data
dateSelected action
getting calendar data
inside promise
inside promise
inside promise

1 Ответ

0 голосов
/ 10 января 2020

Вам нужно вернуть обещание из ваших действий. Возврат обещания undefined (что и происходит в настоящее время) разрешается немедленно.

dateSelected(context, data) {
  return new Promise(resolve => {
    getCalendarData(isBetween.date, context.rootState.userId)
    .then(result => {
      context.commit('SET_MONTHLY_DATA', { result: result.Result, basedOn: isBetween.date });
      resolve();
    }
  }
},

Кроме того, vuex commit не возвращает обещание, поэтому его не имеет смысла ждать.

...