hooks
hooks copied to clipboard
[RFC]是否考虑在useRequest中引入AbortController
目前useRequest的做法,是通过标记在竞态问题出现时,标记忽略之前请求回调(onSuccess)执行。 新加的cancel方法可以主动标记,让service执行结束后的回调(onSuccess)不再执行。
const { cancel } = useRequest(async () => {
const res = await fetch(url);
return res.data;
}, { onSuccess })
但是,这些对于并不能终止service内部的执行。
使用AbortController可以实现fetch的提前中止
const abortControllerRef = useRef();
const { cancel } = useRequest(async () => {
const controller = new AbortController();
abortControllerRef.current = controller;
const res = await fetch(url, { signal: controller.signal });
return res.data;
}, { onSuccess })
const myCancel = () => {
abortControllerRef.current?.abort();
abortControllerRef.current = null;
}
自己实现过于繁琐,看看能否直接在useReuqest的时候,默认生成一个controller,传递给service方法,并且在合适时机自动调用abort方法(竞态时、cancel时)。
// 理想中的接口使用
const { cancel } = useRequest(async (controller) => {
// service中如果包含了多个异步阶段,可以很方便的在任一阶段提前中止
const res1 = await fetch(url1, { signal: controller.signal });
const res2 = await fetch(url2, { data: getDataDepsRes1(), signal: controller.signal });
const res3 = await fetch(url3, { data: getDataDepsRes2(), signal: controller.signal });
const res4 = await fetch(url4, { data: getDataDepsRes3(), signal: controller.signal });
return res.data;
}, { onSuccess })
虽然说覆水难受,已发出去的请求服务器仍然会收到,但仍然一定以上能过做到性能提升
- fetch请求的结果解析,以及一些封在api方法的后置逻辑,均能被最大程度省掉
- 对于一些长pending状态的请求也可以提前释放,结束掉闭包引用等
#862 #2039 https://github.com/alibaba/hooks/issues/1715#issuecomment-1166513696 目前AbortController应该不再属于实验性质了