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

循环调用Graph API遇HTTP 429限流错误,如何获取所有会议室可用性?

问题解决:Graph API调用429错误与批量获取会议室可用性

问题根源

  1. debounce用法错误:debounce的作用是只执行最后一次触发的请求,所以多房间调用时只会返回最后一个房间的结果。
  2. 单房间请求触发速率限制:每个房间单独调用getschedule接口,请求量过大触发Graph API的HTTP 429速率限制。
  3. 异步逻辑缺失:原代码中_getAvailability的API请求是异步的,但同步返回true,无法正确获取实际可用性状态。

解决方案

核心优化点

  • 批量调用getschedule:该接口支持一次性传入最多20个会议室邮箱,大幅减少请求数量。
  • 429错误自动重试:根据响应头的Retry-After值延迟重试,而非固定延迟。
  • 异步状态管理:用Promise和Promise.all处理批量请求,确保所有数据返回后再更新组件状态。

修正后的代码示例

1. 封装带重试的Graph API请求工具函数

private async graphRequestWithRetry(client: MSGraphClientV3, apiPath: string, method: 'get' | 'post', body?: any): Promise<any> {
  try {
    const response = method === 'post' 
      ? await client.api(apiPath).version('v1.0').post(body)
      : await client.api(apiPath).version('v1.0').get();
    return response;
  } catch (err: any) {
    // 处理429速率限制错误
    if (err.statusCode === 429 && err.headers?.['retry-after']) {
      const retryDelay = parseInt(err.headers['retry-after'], 10) * 1000;
      await new Promise(resolve => setTimeout(resolve, retryDelay));
      // 递归重试请求
      return this.graphRequestWithRetry(client, apiPath, method, body);
    }
    throw err;
  }
}

2. 修改会议室列表获取与批量可用性查询逻辑

private async _getRooms(item: RoomListInfo): Promise<void> {
  this.setState({ rooms: [], loading: true }); // 添加加载状态提升体验
  try {
    const client = await this.props.context.msGraphClientFactory.getClient("3");
    
    // 获取当前房间组下的所有会议室
    const roomsResponse = await this.graphRequestWithRetry(
      client,
      `places/${item.emailAddress}/microsoft.graph.roomlist/rooms`,
      'get'
    );
    
    // 初始化会议室数组,先填充基础信息
    const allRooms = roomsResponse.value.map((room: any) => ({
      displayName: room.displayName,
      emailAddress: room.emailAddress,
      capacity: room.capacity,
      id: room.id,
      availability: null // 占位,后续填充可用性状态
    }));

    // 将会议室按20个一组拆分(符合Graph API的批量请求限制)
    const roomGroups = [];
    const groupSize = 20;
    for (let i = 0; i < allRooms.length; i += groupSize) {
      roomGroups.push(allRooms.slice(i, i + groupSize));
    }

    // 批量查询每组会议室的可用性
    for (const group of roomGroups) {
      const scheduleRequest = {
        Schedules: group.map(room => room.emailAddress),
        StartTime: {
          dateTime: this.formattedDateForAvailability(this.state.selectedStart),
          timeZone: "Central Standard Time",
        },
        EndTime: {
          dateTime: this.formattedDateForAvailability(this.state.selectedEnd),
          timeZone: "Central Standard Time",
        },
        availabilityViewInterval: "30",
      };

      const availabilityResponse = await this.graphRequestWithRetry(
        client,
        'me/calendar/getschedule',
        'post',
        scheduleRequest
      );

      // 将可用性结果映射到对应会议室
      availabilityResponse.value.forEach((schedule: any) => {
        const targetRoom = allRooms.find(room => room.emailAddress === schedule.scheduleId);
        if (targetRoom) {
          // availabilityView为"0"表示空闲,否则为忙碌
          targetRoom.availability = schedule.availabilityView === "0";
        }
      });
    }

    // 所有请求完成后更新组件状态
    this.setState({ rooms: allRooms, loading: false });
  } catch (err) {
    console.error("获取会议室数据失败:", err);
    this.setState({ loading: false });
  }
}

3. 移除原有_getAvailability函数

批量请求已经解决了速率问题,无需保留原有的debounce函数。


额外优化建议

  • 加载状态提示:在请求过程中显示加载动画,避免用户误以为页面无响应。
  • 结果缓存:如果用户未修改查询时间或会议室组,缓存之前的查询结果,减少重复请求。
  • 用户友好的错误提示:将错误信息展示在页面上,而非仅打印到控制台。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:40:30