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

Unity Cloud Save API与Next.js 15的Fetch请求超时问题

解决Next.js路由调用Unity Cloud Save API的连接超时及CSV下载问题

问题根源

你当前的代码通过Promise.all一次性发起最多1000个请求到Unity Cloud Save API,这种高并发会触发API限流、耗尽服务器连接资源,直接导致ConnectTimeoutError;同时大量请求的处理时间会拖长接口响应,引发前端CSV下载超时。

解决方案

1. 限制并发请求数量

用p-limit库控制同时发起的请求数,避免一次性打满API接口:

首先安装依赖:

npm install p-limit

修改后的路由代码:

import pLimit from 'p-limit';
import { NextResponse } from 'next/server';

export async function GET() {
  const bearerToken = await getBearerToken();

  // 获取排行榜数据
  const res = await fetch(
    `https://leaderboards.services.api.unity.com/v1/projects/${UNITY_PROJECT_ID_FRED}/leaderboards/luxembourg/scores?limit=1000`,
    {
      headers: {
        Authorization: `Bearer ${bearerToken}`,
        'Content-Type': 'application/json',
      },
    }
  );

  if (!res.ok) {
    return NextResponse.json(
      { error: 'Failed to fetch leaderboard' },
      { status: res.status }
    );
  }

  const leaderboard: LeaderboardResponse = await res.json();
  const playerIds = leaderboard.results?.map((r) => r.playerId) ?? [];

  // 限制同时并发请求数为5,可根据Unity API限流规则调整
  const limit = pLimit(5);

  // 包装请求并限制并发
  const emailRequests = playerIds.map((playerId) =>
    limit(async () => {
      try {
        const emailRes = await fetch(
          `https://cloud-save.services.api.unity.com/v1/data/projects/${UNITY_PROJECT_ID_FRED}/players/${playerId}/public/items?keys=Email`,
          {
            headers: {
              Authorization: `Bearer ${bearerToken}`,
              'Content-Type': 'application/json',
            },
            // 设置合理超时时间,避免过早断开
            signal: AbortSignal.timeout(30000),
          }
        );

        if (!emailRes.ok) {
          return { playerId, email: null };
        }

        const data = await emailRes.json();
        const emailItem = data.results?.find((r) => r.key === 'Email');
        return { playerId, email: emailItem?.value ?? null };
      } catch (err) {
        console.error(`Failed to fetch email for player ${playerId}:`, err);
        return { playerId, email: null };
      }
    })
  );

  const emails = await Promise.all(emailRequests);

  return NextResponse.json({ emails });
}

2. 优先使用批量API(推荐)

检查Unity Cloud Save官方文档,确认是否支持批量获取多个玩家公开数据的接口。如果存在,将多个playerId打包成单个请求,能把请求次数从1000次压缩到几次,彻底解决超时问题。

示例批量请求逻辑(需以官方API为准):

// 按50个玩家一组拆分请求
const batchSize = 50;
const emailBatchRequests = [];

for (let i = 0; i < playerIds.length; i += batchSize) {
  const batch = playerIds.slice(i, i + batchSize);
  emailBatchRequests.push(
    fetch(
      `https://cloud-save.services.api.unity.com/v1/data/projects/${UNITY_PROJECT_ID_FRED}/players/public/items?keys=Email&playerIds=${batch.join(',')}`,
      {
        headers: {
          Authorization: `Bearer ${bearerToken}`,
          'Content-Type': 'application/json',
        },
      }
    ).then(res => res.json())
  );
}

// 处理批量返回的数据
const batchResults = await Promise.all(emailBatchRequests);
const emails = batchResults.flatMap(batch => 
  batch.results.map(item => ({
    playerId: item.playerId,
    email: item.key === 'Email' ? item.value : null
  }))
);

3. 优化CSV下载体验

如果后端响应仍偏长,可改用Next.js流式响应,让前端逐步接收数据,避免整体超时:

import { Readable } from 'stream';
import { NextResponse } from 'next/server';

export async function GET() {
  // ... 前面的排行榜、邮件获取逻辑 ...

  // 生成CSV内容
  const csvRows = [
    ['Player ID', 'Email'],
    ...emails.map(e => [e.playerId, e.email || '']),
  ];
  const csvContent = csvRows.map(row => row.join(',')).join('\n');

  // 流式返回CSV
  const stream = Readable.from([csvContent]);

  return new NextResponse(stream, {
    headers: {
      'Content-Type': 'text/csv',
      'Content-Disposition': 'attachment; filename="player-emails.csv"',
    },
  });
}

4. 其他补充优化

  • 增加错误重试:用p-retry库对失败的请求进行重试,避免单次网络波动导致失败
  • 缓存Bearer Token:如果getBearerToken()每次请求都重新获取,可缓存一段时间,减少认证请求开销
  • 对齐API限流规则:查阅Unity官方文档的速率限制,调整并发数到允许范围内

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 09:22:45