【问题标题】:React cancel out of Promise on props changeReact cancel out of Promise on props change
【发布时间】:2020-06-03 02:43:22
【问题描述】:

我有一个采用 visible bool 属性的 React 组件。 react 执行一个触发长时间运行的 Promise 的函数,当visible 更改时,我需要取消 Promise。然而,试图从外部拒绝 Promise 并不会停止执行。

代码的大致轮廓如下所示:

<ComponentA visible={visible} />
const ComponentA = ({ visible }) => {
   const [rejectFn, setRejectFn] = useState(() = () => console.log('test');

    useEffect(() => {
        if (visible) {
            ...
        } else {
            setRejectFn();
        }
    }, [visible]);

   const promiseFn = () => (
       new Promise((resolve, reject) => {
            // logic

            const endCallback = (error) => {
                if (error) {
                    reject(error);
                    console.log('error', error);
                } else {
                    resolve(...);
                }
            };

            setRejectFn(() = () => endCallback('exit early'));

            someOtherFn(..., endCallback); // processing file chunk by chunk
       })
   );

   const onDivClick = () => (
      // set some state vars
      promiseFn()
          .then(() => ...)
          .catch(() => ...)
          .finally(() => ...);
   );

   return (
      <div onClick=(onDivClick) />
   );
}

上述代码将触发rejectFn 并记录"exit early",但Promise 将继续执行直到完成。

【问题讨论】:

  • 按照设计承诺保证总是解决(或出错)。您可以通过无操作来模拟取消,但它应该始终按设计解决。
  • 您的代码也不会在重新渲染时清理 Promise,这可能会导致重复调用和 Promise 解析。
  • 为什么不多说一些关于这个长时间运行的代码?如果是某种计算,则需要在该计算内部检查 Promise 是否已“取消”并停止计算。喜欢returnthrow,不管最快的出路是什么。
  • @Thomas 长时间运行的代码基本上是这样的:stackoverflow.com/a/39112502/4781945

标签: javascript reactjs promise react-hooks es6-promise


【解决方案1】:

给你:

你不能取消正在进行的承诺请求,但你可以这样做

  const visibleRef = useRef(visible); // using ref to get latest value inside setInterval

  useEffect(() => {
    visibleRef.current = visible;
    console.log("visible", visible);
  }, [visible]); // <--- Set the value of visible whenever it changes

  const promiseFn = () =>
    new Promise((resolve, reject) => {
      // logic

      // Will check visibleRef.current every second , you can reduce the time as your need
      const interval = setInterval(() => {
        if (!visibleRef.current) { 
          reject("Due to Visible false value");
          clearInterval(interval);
        }
      }, 1000); 

      // just to mock the promise event execution
      setTimeout(() => {
        resolve();
        clearInterval(interval);
      }, 5000);
    });

工作演示

请检查控制台,这将帮助您了解演示

【讨论】:

  • 您的演示与主题无关,您可以轻松取消“长时间运行的任务”,因为您使用的是setTimeout,但someOtherFn(..., endCallback); 是一些更复杂的东西,在主题cmets:stackoverflow.com/questions/39112096/…
  • 感谢您的评论,我使用设置的超时时间只是为了模拟与 someotherfn 相同的进程,您可以通过检查我在内部使用的可见性来停止这些。
  • 如果无法取消someOtherFn(..., endCallback);,演示将不会提供任何价值。最好查看主题的 cmets,其中定义了更多的主题说明。
  • 我认为你应该检查演示,点击做出承诺请求,这将需要 5 秒才能完成,如果在此之前你切换可见它会导致承诺被拒绝,这是我对问题的理解,阅读问题的第一段,如果这不是OP想要的,我会很乐意删除我的答案:)
猜你喜欢
  • 2021-02-01
  • 2020-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-02
  • 2022-08-08
相关资源
最近更新 更多