Skip to content

[RFC]是否考虑在useRequest中引入AbortController #2593

Open
@chqcose

Description

@chqcose

目前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
#1715 (comment) 目前AbortController应该不再属于实验性质了

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew feature or requestv4

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions