From e830034d033650ad2c7b6d7ced3227b7464ad1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Wed, 7 Oct 2026 14:11:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=B8=E6=88=8F=E5=AA=92=E4=BD=93=E6=8D=A2?= =?UTF-8?q?=E7=AD=BE=E8=AF=B7=E6=B1=82=E6=94=AF=E6=8C=81=E5=8F=96=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - getGameDistributionMediaReadUrl / getOwnerGameDistributionMediaReadUrl 增加可选 AbortSignal 并透传 - resolveGamePublishImagePreview 转发 signal;useGameDistributionMediaReadUrl 在 effect 清理时 abort 在途请求 --- src/components/game-distribution/gamePublishAssets.ts | 3 +++ .../useGameDistributionMediaReadUrl.ts | 10 +++++++++- src/services/gameDistributionClient.ts | 6 ++++-- 3 files changed, 16 insertions(+), 3 deletions(-) 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);