You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确await异步防抖函数?解决await立即生效问题

问题:await防抖后的异步API调用未生效,控制台立即打印'Awaited'

我尝试await一个经过防抖处理的异步API调用,但await未生效,控制台会立即打印'Awaited',想知道哪里出错了。

我的代码

onMounted中的代码

onMounted(async () => {
  console.log('Awaiting');
  const fetchAbsentiesAsync = await apiCallConst();
  await Promise.all([fetchAbsentiesAsync]);
  console.log('Awaited');

  isLoading.value = false;
});

API调用代码

import debounce from 'lodash/debounce';

const apiCallConst = debounce(async () => {
  await ApiService.makeApiCall()
    .then((data) => {
      state.data = data;
    })
}, 10000);

ApiService.makeApiCall代码

async makeApiCall(): Promise<string> {
  return {
    data: await apiFetch(`group/data`, {
      method: HttpMethods.POST,
    }),
  };
}

问题原因

lodash的debounce函数默认不会返回原异步函数的Promise,它返回的防抖函数调用后,不会等待内部的异步操作完成,而是直接返回undefined。所以你这里的await apiCallConst()实际上是在等待一个undefined,自然会立即执行后续代码,不会等待防抖后的API请求完成。

另外原代码里还有两处冗余:

  • const fetchAbsentiesAsync = await apiCallConst(); 因为apiCallConst()返回undefined,所以这个变量没有意义
  • await Promise.all([fetchAbsentiesAsync]) 等同于等待一个包含undefined的数组,完全起不到等待异步操作的作用

解决方案

方案1:封装支持Promise的防抖函数

自己实现一个能返回Promise的防抖函数,让调用者可以通过await等待防抖后的异步操作完成:

function debouncePromise(func, wait) {
  let timeoutId;
  let resolveQueue = [];

  return function(...args) {
    return new Promise((resolve) => {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(async () => {
        const result = await func.apply(this, args);
        // 批量resolve所有等待的Promise
        resolveQueue.forEach(r => r(result));
        resolveQueue = [];
      }, wait);
      resolveQueue.push(resolve);
    });
  };
}

然后用这个函数替换lodash的debounce:

const apiCallConst = debouncePromise(async () => {
  const data = await ApiService.makeApiCall();
  state.data = data;
}, 10000);

这样在onMounted中调用await apiCallConst()就会正确等待防抖后的API请求完成,之后才会打印'Awaited'。

方案2:简化原代码逻辑(如果不需要防抖的累积处理)

如果只是想要延迟执行一次API调用,不需要防抖的“多次触发取最后一次”的特性,可以直接用setTimeout配合Promise:

const apiCallConst = () => {
  return new Promise(resolve => {
    setTimeout(async () => {
      const data = await ApiService.makeApiCall();
      state.data = data;
      resolve(data);
    }, 10000);
  });
};

这样同样可以通过await apiCallConst()等待操作完成。

额外优化建议

原API调用代码中混用了await和.then(),可以简化为纯await写法,提升可读性:

// 优化后的apiCallConst(配合自定义的debouncePromise)
const apiCallConst = debouncePromise(async () => {
  const data = await ApiService.makeApiCall();
  state.data = data;
}, 10000);

内容的提问来源于stack exchange,提问作者Ruben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 05:37:29