diff --git a/src/components/game-distribution/gamePublishAssets.ts b/src/components/game-distribution/gamePublishAssets.ts index 831252f81..3a1c1e17f 100644 --- a/src/components/game-distribution/gamePublishAssets.ts +++ b/src/components/game-distribution/gamePublishAssets.ts @@ -147,6 +147,7 @@ export function revokeGamePublishImagePreview( export async function resolveGamePublishImagePreview( objectKey: string, gameId?: string, + signal?: AbortSignal, ) { const normalizedKey = objectKey.trim(); if (!normalizedKey) return ''; @@ -157,10 +158,12 @@ export async function resolveGamePublishImagePreview( normalizedGameId, normalizedKey, GAME_PUBLISH_IMAGE_PREVIEW_EXPIRE_SECONDS, + signal, ) : await getGameDistributionMediaReadUrl( normalizedKey, GAME_PUBLISH_IMAGE_PREVIEW_EXPIRE_SECONDS, + signal, ); } catch { return ''; diff --git a/src/components/game-distribution/useGameDistributionMediaReadUrl.ts b/src/components/game-distribution/useGameDistributionMediaReadUrl.ts index 68b2b1137..373adac5a 100644 --- a/src/components/game-distribution/useGameDistributionMediaReadUrl.ts +++ b/src/components/game-distribution/useGameDistributionMediaReadUrl.ts @@ -40,6 +40,7 @@ export function useGameDistributionMediaReadUrl( return; } + const controller = new AbortController(); let cancelled = false; setResolvedUrl(''); setIsResolving(true); @@ -48,8 +49,13 @@ export function useGameDistributionMediaReadUrl( resolvedGameId, normalizedKey, options.expireSeconds, + controller.signal, ) - : getGameDistributionMediaReadUrl(normalizedKey, options.expireSeconds); + : getGameDistributionMediaReadUrl( + normalizedKey, + options.expireSeconds, + controller.signal, + ); resolve .then((nextUrl) => { if (!cancelled) setResolvedUrl(nextUrl); @@ -63,6 +69,8 @@ export function useGameDistributionMediaReadUrl( return () => { cancelled = true; + // 取消已在途的换签请求:objectKey/gameId 快速切换时不再让旧请求白占 API 配额。 + controller.abort(); }; }, [normalizedKey, resolvedGameId, options.expireSeconds, shouldResolve]); diff --git a/src/services/gameDistributionClient.ts b/src/services/gameDistributionClient.ts index 1d6e3f178..c5fa43080 100644 --- a/src/services/gameDistributionClient.ts +++ b/src/services/gameDistributionClient.ts @@ -423,11 +423,12 @@ function readGameDistributionMediaSignedUrl( export async function getGameDistributionMediaReadUrl( objectKey: string, expireSeconds?: number, + signal?: AbortSignal, ) { const params = buildGameDistributionMediaReadParams(objectKey, expireSeconds); const payload = await requestJson( `/media/read-url?${params.toString()}`, - { method: 'GET', cache: 'no-store' }, + { method: 'GET', cache: 'no-store', signal }, '读取游戏媒体地址失败', PUBLIC_GAME_REQUEST_OPTIONS, ); @@ -444,13 +445,14 @@ export async function getOwnerGameDistributionMediaReadUrl( gameId: string, objectKey: string, expireSeconds?: number, + signal?: AbortSignal, ) { const normalizedGameId = gameId.trim(); if (!normalizedGameId) throw new Error('缺少作品标识'); const params = buildGameDistributionMediaReadParams(objectKey, expireSeconds); const payload = await requestJson( `/my-games/${encodeURIComponent(normalizedGameId)}/media/read-url?${params.toString()}`, - { method: 'GET', cache: 'no-store' }, + { method: 'GET', cache: 'no-store', signal }, '读取作品媒体地址失败', ); return readGameDistributionMediaSignedUrl(payload);