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

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

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

你的问题核心很明确:同步函数没法直接等待异步操作完成,因为getHolidaysByYear是异步函数,它的.then()回调会在当前同步代码执行完之后才触发,所以你看到的日志顺序是before→after→holidays,而不是你期望的顺序。下面给你两种可行的解决方案,根据你的组件场景选择:

方案一:把isHoliday改成异步函数(最直接)

既然要等待异步结果,最直接的方式就是让isHoliday本身变成异步函数,用async/await语法等待getHolidaysByYear的结果:

async function isHoliday(current : Moment) : Promise<boolean> {
  // 其他逻辑(缓存等)
  let year : number = current.toDate().getFullYear();
  let dates : Date[] = [];
  console.log("before : " + dates.length);
  
  // 用await暂停执行,直到异步函数返回结果
  dates = await getHolidaysByYear(year);
  
  console.log("after : " + dates.length);
  // 其他逻辑(判断current是否在节假日列表中)
  return dates.some(date => moment(date).isSame(current, 'day'));
}

注意事项:

改完之后,调用isHoliday的地方也必须用await或者.then()来处理结果,因为它现在返回的是Promise<boolean>。比如在组件的生命周期钩子或事件处理函数中:

// 示例:React组件中调用
useEffect(() => {
  async function checkToday() {
    const isTodayHoliday = await isHoliday(moment());
    console.log("今天是否是节假日?", isTodayHoliday);
  }
  checkToday();
}, []);

方案二:预加载节假日数据(适合必须同步的场景)

如果你的业务场景要求isHoliday必须是同步函数(比如某些组件渲染逻辑不支持异步),那可以提前在组件初始化时加载好节假日数据,存在状态里,让isHoliday直接使用同步的状态数据:

以React为例:

import { useState, useEffect } from 'react';
import moment from 'moment';

// 缓存已加载的节假日,避免重复请求
const holidayCache: Record<number, Date[]> = {};

async function getHolidaysByYear(year : number) : Promise<Date[]> {
  if (holidayCache[year]) {
    return holidayCache[year];
  }
  let dates = await api.request(year);
  const result = dates || [];
  holidayCache[year] = result;
  console.log("holidays : " + result.length);
  return result;
}

function HolidayChecker() {
  const [holidays, setHolidays] = useState<Date[]>([]);
  const [currentYear, setCurrentYear] = useState(new Date().getFullYear());

  // 初始化或年份变化时加载数据
  useEffect(() => {
    async function loadHolidays() {
      const data = await getHolidaysByYear(currentYear);
      setHolidays(data);
    }
    loadHolidays();
  }, [currentYear]);

  // 现在isHoliday是同步函数,直接用状态中的数据
  function isHoliday(current : Moment) : boolean {
    const year = current.toDate().getFullYear();
    // 如果当前年份未加载,先触发加载并返回默认值(或显示加载状态)
    if (year !== currentYear) {
      setCurrentYear(year);
      return false;
    }
    console.log("before : " + holidays.length);
    console.log("after : " + holidays.length);
    return holidays.some(date => moment(date).isSame(current, 'day'));
  }

  return (
    <div>
      {isHoliday(moment()) ? "今天是节假日🎉" : "今天不是节假日💼"}
    </div>
  );
}

为什么你的原代码会出现顺序问题?

JavaScript是单线程的,异步操作会被放到事件队列中,等当前同步代码执行完之后才会执行。你的原代码中:

  1. 先打印before : 0
  2. 调用getHolidaysByYear,但它是异步的,直接进入事件队列等待
  3. 立刻打印after : 0(此时dates还没被赋值)
  4. 等接口请求完成,才会执行.then()里的dates = values,然后打印holidays : 143

这就是为什么日志顺序和你期望的相反。

内容的提问来源于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:05:52