【问题标题】:Debounce Vuex Action Call to Database Not Working对数据库的去抖动 Vuex 操作调用不起作用
【发布时间】:2020-04-26 04:27:06
【问题描述】:

我有一些组件可以单独或在同一页面上。这些组件中的每一个都使用相同的 Vuex 状态。由于它们都可以在其他页面上使用并且仍然可以工作,因此它们中的每一个都向同一个 Vuex action 发送调用,而后者又调用使用 axios 的服务 获取 JSON 数据。

所有这些都很棒!

但是,当我在一个页面上确实有 2 个(或更多)这些组件时,axios 调用会为每个组件调用 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;
};

Axios 包装器

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;
};

如果我在 getCalendarData 调用之前、之后和内部以及 getCaledarDataDebounced 方法中放置 console.log 消息:(假设页面上只有 2 个组件)日志显示之前的 2,然后显示之后的 2日志出现。接下来是上面提到的 2 个组件中的每一个的错误,然后记录一个“getCalendarData 内部”,最后记录来自实际获取数据的去抖动版本中的日志。

因此,似乎去抖功能正在发挥作用,因为它只运行了一次。但似乎await call let result = await getCalendarData(isBetween.date, context.rootState.userId); 并不是真正的Waiting。

我错过了什么吗?

回答后编辑

根据@JakeHamTexas 的回答,我现在的dateSelected 中的action 是(实际的完整代码,没有像上面那样删除,以免混淆任何东西):

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');
},

我对@9​​87654341@ 的 API 调用现在是:

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

【问题讨论】:

    标签: vue.js vuex debounce


    【解决方案1】:

    您需要从您的操作中返回一个承诺。返回未定义的承诺(这是当前正在发生的事情)立即解决。

    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 不返回承诺,因此等待它没有意义。

    【讨论】:

    • 我终于有时间回到这个问题上,谢谢你的回答,我已经编辑了我的代码和上面的问题。仍然调用 API 3 次。
    • 你能@JakeHamTexas 根据我的编辑提供任何建议吗?
    猜你喜欢
    • 2013-05-17
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 2021-10-26
    • 2021-11-28
    • 2017-02-20
    • 2020-10-01
    • 2018-11-30
    相关资源
    最近更新 更多