我有一个 React 组件,有 3 个按钮,代表用户可以做出的 3 个选择。 如果用户单击一个按钮,然后单击另一个按钮,我会使用
AbortController.signal.abort()
取消之前的 HTTP 请求,这真的非常简单。
问题是,该方法的 try {} catch {} finally {}
块中有一个
loading状态。 当我取消第一个承诺时,http 请求实际上被取消,但第二个承诺在第一个承诺达到其最终范围之前开始运行..在第二个承诺完成之前进行
loader
-> false
。
export default function SingleTesterQuestion({
question,
}: {
question: SomeType;
}) {
const controller = useRef(new AbortController());
const [loading, setLoading] = useState(false);
const updateQuestionInServerForSpecificId = useCallback(
async (choice: string) => {
try {
// if same question with same id got clicked on
// different buttons (fast) abort the previous request
controller.current.abort();
controller.current = new AbortController();
setLoading(true);
await httpMethods.answerSimulationTestQuestion(
question.id,
choice,
controller.current.signal
);
// update some store
} catch (error) {
//
} finally {
setLoading(false);
}
},
[question.id]
);
return (
<Box>
<Choices updateQuestionInServerForSpecificId={updateQuestionInServerForSpecificId} />
</Box>
);
}
signal.onabort()
的功能)
export default function SingleTesterQuestion({
question,
}: {
question: SomeType;
}) {
const controller = useRef<null | AbortController>(null);
const [loading, setLoading] = useState(false);
const req = async (choice: string) => {
try {
// if same question with same id got clicked on
// different buttons (fast) abort the previous request
controller.current = new AbortController();
setLoading(true);
await httpMethods.answerSimulationTestQuestion(
question.id,
choice,
controller.current.signal
);
// update some store
} catch (error) {
//
} finally {
controller.current = null;
setLoading(false);
}
};
const updateQuestionInServerForSpecificId = async (
choice: string
) => {
if (!controller.current) {
// no one has yet to create an AbortController
// make the request here
await req(choice);
return;
}
// there is already an AbortController out there
controller.current.signal.onabort = async (x) => {
await req(choice);
};
controller.current.abort();
};
return (
<Box>
<Choices updateQuestionInServerForSpecificId={updateQuestionInServerForSpecificId} />
</Box>
);
}
方法就是这样:
async answerSimulationTestQuestion(
questionId: string,
choice: string,
signal: GenericAbortSignal
): Promise<boolean> {
const { data } = await axios.put<boolean>(
`url...`,
{ choice },
{ params: { questionId }, signal }
);
return data;
}
我不会说我喜欢使用finally,我认为这会在不运行finally块的情况下突破函数
catch(error) {
if (controller.current.signal.aborted) return
}