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

如何在TypeScript同步函数中获取异步函数的返回结果?

解决同步函数中等待异步结果的问题

这问题我太熟了——你现在的核心痛点就是同步函数没办法直接等待异步操作完成。JavaScript的事件循环机制决定了,异步代码(比如getHolidaysByYear里的await和后续的.then回调)会在所有同步代码执行完之后才会触发,所以你看到的日志顺序才是before:0、after:0先输出,最后才是holidays:143。

下面给你两种实用的解决方案,适配不同的组件使用场景:

方案一:把isHoliday改成异步函数,组件中处理异步逻辑

既然依赖的是异步接口,最直接的方式就是让isHoliday也变成异步函数,然后在组件里用async/await来处理结果。同时别忘了加缓存,避免重复请求接口。

修改后的代码示例

// 保留原异步接口,简化空值处理
async function getHolidaysByYear(year: number): Promise<Date[]> {
  const dates = await api.request(year);
  return dates ?? [];
}

// 全局缓存,避免重复请求
const holidayCache = new Map<number, Date[]>();

// 改为异步函数
async function isHoliday(current: Moment): Promise<boolean> {
  const year = current.toDate().getFullYear();
  let dates: Date[];

  // 先查缓存,有就直接用
  if (holidayCache.has(year)) {
    dates = holidayCache.get(year)!;
  } else {
    // 没有就调用接口,并存进缓存
    dates = await getHolidaysByYear(year);
    holidayCache.set(year, dates);
    console.log("holidays:", dates.length);
  }

  console.log("after:", dates.length);
  // 核心判断逻辑:检查当前日期是否在节假日列表中
  return dates.some(date => moment(date).isSame(current, 'day'));
}

组件中使用示例(以React为例)

function HolidayDisplay({ currentDate }: { currentDate: Moment }) {
  const [isHolidayResult, setIsHolidayResult] = useState<boolean | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 用异步函数包裹,处理isHoliday的结果
    const checkHoliday = async () => {
      setLoading(true);
      const result = await isHoliday(currentDate);
      setIsHolidayResult(result);
      setLoading(false);
    };

    checkHoliday();
  }, [currentDate]);

  if (loading) return <div>正在查询节假日...</div>;
  return (
    <div>
      {isHolidayResult ? "🎉 今天是节假日!" : "💼 今天是工作日"}
    </div>
  );
}

方案二:预加载节假日数据,让isHoliday保持同步

如果你的组件必须在同步逻辑中使用isHoliday(比如渲染时直接判断),可以提前在组件挂载阶段预加载需要的年份数据,存到缓存里。这样isHoliday执行时就能直接拿到同步的缓存数据。

预加载+同步判断的代码示例

// 全局缓存和加载状态(避免重复请求)
const holidayCache = new Map<number, Date[]>();
const loadingPromises = new Map<number, Promise<void>>();

// 预加载指定年份的节假日数据
async function preloadHolidays(year: number) {
  // 已有缓存直接返回
  if (holidayCache.has(year)) return;
  // 正在加载就等待加载完成
  if (loadingPromises.has(year)) await loadingPromises.get(year);

  // 发起请求并更新缓存
  const loadPromise = (async () => {
    const dates = await getHolidaysByYear(year);
    holidayCache.set(year, dates);
    console.log("holidays:", dates.length);
  })();

  loadingPromises.set(year, loadPromise);
  await loadPromise;
  loadingPromises.delete(year);
}

// 保持同步的isHoliday,前提是数据已预加载
function isHoliday(current: Moment): boolean {
  const year = current.toDate().getFullYear();
  const dates = holidayCache.get(year) || [];
  console.log("after:", dates.length);
  return dates.some(date => moment(date).isSame(current, 'day'));
}

组件中使用示例

function HolidayDisplay({ currentDate }: { currentDate: Moment }) {
  const [dataLoaded, setDataLoaded] = useState(false);

  useEffect(() => {
    const year = currentDate.toDate().getFullYear();
    // 组件挂载时预加载对应年份的节假日数据
    preloadHolidays(year).then(() => setDataLoaded(true));
  }, [currentDate]);

  if (!dataLoaded) return <div>加载中...</div>;
  return (
    <div>
      {isHoliday(currentDate) ? "🎉 今天是节假日!" : "💼 今天是工作日"}
    </div>
  );
}

方案选择建议

  • 如果isHoliday是在**用户交互(比如点击按钮)**时触发,方案一更简单直接;
  • 如果isHoliday是在组件渲染阶段就需要用到,方案二更合适,避免渲染逻辑中混入异步代码导致的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:02:19