40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
// Polling is bounded by elapsed time, including network waits. Terminal provider failures
|
|
// must escape immediately instead of being converted into a perpetual pending response.
|
|
export class EnhanceTerminalError extends Error {}
|
|
export async function pollTaskResult(
|
|
apiUrl: string,
|
|
apiKey: string,
|
|
taskId: string,
|
|
delay = 1000,
|
|
timeout = 120000,
|
|
fetcher: typeof fetch = fetch,
|
|
): Promise<any> {
|
|
const deadline = Date.now() + timeout;
|
|
while (Date.now() < deadline) {
|
|
try {
|
|
const response = await fetcher(
|
|
`${apiUrl}/api/tasks/visual/scale/${encodeURIComponent(taskId)}`,
|
|
{
|
|
method: "GET",
|
|
headers: { "X-API-KEY": apiKey },
|
|
signal: AbortSignal.timeout(Math.max(1, Math.min(10000, deadline - Date.now()))),
|
|
},
|
|
);
|
|
if (!response.ok) throw Error(`轮询请求失败: ${response.status}`);
|
|
const result = await response.json();
|
|
if (!result.data) throw Error("高清查询未返回任务状态");
|
|
if (result.data.state < 0)
|
|
throw new EnhanceTerminalError(
|
|
`AOS任务失败: ${String(result.data.err_message || result.data.err_info || result.data.state_detail || result.data.state)}`,
|
|
);
|
|
if (result.data.progress >= 100) return result;
|
|
} catch (error) {
|
|
if (error instanceof EnhanceTerminalError) throw error;
|
|
}
|
|
const remaining = deadline - Date.now();
|
|
if (remaining > 0)
|
|
await new Promise((resolve) => setTimeout(resolve, Math.min(delay, remaining)));
|
|
}
|
|
throw Error("轮询超时");
|
|
}
|