React 组件 - 在开始新的 Promise 之前,等待先前的 Promise 方法 (fetch) 到达其 finally {} 块(使用 AbortController 取消)

问题描述 投票:0回答:1

我有一个 React 组件,有 3 个按钮,代表用户可以做出的 3 个选择。 如果用户单击一个按钮,然后单击另一个按钮,我会使用

AbortController.signal.abort()
取消之前的 HTTP 请求,这真的非常简单。

问题是,该方法的 try {} catch {} finally {} 块中有一个

loading
状态。 当我取消第一个承诺时,http 请求实际上被取消,但第二个承诺在第一个承诺达到其最终范围之前开始运行..在第二个承诺完成之前进行
loader
->
false

  1. 首次点击 -> 第一个承诺运行
  2. 再次点击 -> 第二个 Promise 运行
  3. 第一个 HTTP 被取消
  4. 新请求开始
  5. 最后调用/运行的第一个函数的 {} 块
  6. 第二个函数的finally {} 块被调用/运行

我尝试用两种方式做到这一点:

第一种方法


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;
  }

有办法解决这个问题吗?

reactjs asynchronous promise components abortcontroller
1个回答
0
投票

我不会说我喜欢使用finally,我认为这会在不运行finally块的情况下突破函数

catch(error) {
if (controller.current.signal.aborted) return
}
© www.soinside.com 2019 - 2024. All rights reserved.