fix(frontend): RefineView 取消在途 refine——AbortController 防段切换竞态(CR-H12)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useState } from "react";
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
|
||||
import { api } from "@/lib/api/client";
|
||||
import { useToast } from "@/components/Toast";
|
||||
@@ -24,6 +24,8 @@ export interface UseRefine {
|
||||
segment: string,
|
||||
instruction?: string,
|
||||
) => Promise<RefineResult | null>;
|
||||
// 取消在途回炉(段切换/卸载时调用)——不触碰 state,安全用于 effect 清理。
|
||||
abort: () => void;
|
||||
reset: () => void;
|
||||
}
|
||||
|
||||
@@ -32,10 +34,15 @@ export interface UseRefine {
|
||||
export function useRefine(): UseRefine {
|
||||
const [status, setStatus] = useState<RefineStatus>("idle");
|
||||
const [result, setResult] = useState<RefineResult | null>(null);
|
||||
const controllerRef = useRef<AbortController | null>(null);
|
||||
const toast = useToast();
|
||||
|
||||
const refine = useCallback<UseRefine["refine"]>(
|
||||
async (projectId, chapterNo, segment, instruction) => {
|
||||
// 取消上一次在途请求,换新 controller(段切换竞态防护,CR-H12)。
|
||||
controllerRef.current?.abort();
|
||||
const controller = new AbortController();
|
||||
controllerRef.current = controller;
|
||||
setStatus("refining");
|
||||
setResult(null);
|
||||
try {
|
||||
@@ -46,8 +53,11 @@ export function useRefine(): UseRefine {
|
||||
path: { project_id: projectId, chapter_no: chapterNo },
|
||||
},
|
||||
body: buildRefineRequest(segment, instruction),
|
||||
signal: controller.signal,
|
||||
},
|
||||
);
|
||||
// 已被后续请求/卸载中止:丢弃迟到响应,不写状态。
|
||||
if (controller.signal.aborted) return null;
|
||||
if (error || !data) {
|
||||
setStatus("error");
|
||||
const code = errorCode(error);
|
||||
@@ -67,6 +77,8 @@ export function useRefine(): UseRefine {
|
||||
setStatus("done");
|
||||
return outcome;
|
||||
} catch {
|
||||
// 主动中止(abort)触发的异常不该报错 toast。
|
||||
if (controller.signal.aborted) return null;
|
||||
setStatus("error");
|
||||
toast("回炉请求异常,请检查网络。", "error");
|
||||
return null;
|
||||
@@ -75,10 +87,18 @@ export function useRefine(): UseRefine {
|
||||
[toast],
|
||||
);
|
||||
|
||||
// 仅取消在途请求,不触碰 state——可安全用于 effect 清理 / 卸载。
|
||||
const abort = useCallback((): void => {
|
||||
controllerRef.current?.abort();
|
||||
controllerRef.current = null;
|
||||
}, []);
|
||||
|
||||
const reset = useCallback((): void => {
|
||||
controllerRef.current?.abort();
|
||||
controllerRef.current = null;
|
||||
setStatus("idle");
|
||||
setResult(null);
|
||||
}, []);
|
||||
|
||||
return { status, result, refine, reset };
|
||||
return { status, result, refine, abort, reset };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user