首页 > 解决方案 > 取消卸载承诺中的多个承诺?

问题描述

嗨,由于收到警告,我想取消卸载承诺,

警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消componentWillUnmount方法中的所有订阅和异步任务。

我的代码:

const makeCancelable = (promise: Promise<void>) => {
  let hasCanceled_ = false;

  const wrappedPromise = new Promise((resolve, reject) => {
    promise.then(
      (val) => (hasCanceled_ ? reject({ isCanceled: true }) : resolve(val)),
      (error) => (hasCanceled_ ? reject({ isCanceled: true }) : reject(error))
    );
  });

  return {
    promise: wrappedPromise,
    cancel() {
      hasCanceled_ = true;
    },
  };
};

useEffect(() => {
  const initialize = async () => {
    const getImageFilesystemKey = (remoteUri: string) => {
      const [_, fileName] = remoteUri.split('toolbox-talks/');
      return `${cacheDirectory}${fileName}`;
    };
    const filesystemUri = getImageFilesystemKey(uri);
    try {
      // Use the cached image if it exists
      const metadata = await getInfoAsync(filesystemUri);

      if (metadata.exists) {
        console.log('resolve 1');
        setFileUri(filesystemUri);
      } else {
        const imageObject = await downloadAsync(uri, filesystemUri);
        console.log('resolve 2');
        setFileUri(imageObject.uri);
      }
      // otherwise download to cache
    } catch (err) {
      console.log('error 3');
      setFileUri(uri);
    }
  };
  const cancelable = makeCancelable(initialize());
  cancelable.promise
    .then(() => {
      console.log('reslved');
    })
    .catch((e) => {
      console.log('e ', e);
    });
  return () => {
    cancelable.cancel();
  };
}, []);

但我仍然在快速按下时收到警告,请帮帮我?

标签: javascriptreactjs

解决方案


您正在取消承诺,但您并没有取消 axios 调用或在它内部发生的任何逻辑initialize()。因此,虽然控制台不会打印resolvedsetFileUri但无论如何都会被调用,这会导致您的问题。

解决方案可能如下所示(未经测试):

const makeCancelable = (promise: Promise<void>) => {
  let hasCanceled_ = false;

  const wrappedPromise = new Promise((resolve, reject) => {
    promise.then(
      val => (hasCanceled_ ? reject({ isCanceled: true }) : resolve(val)),
      error => (hasCanceled_ ? reject({ isCanceled: true }) : reject(error))
    );
  });

  return {
    promise: wrappedPromise,
    cancel() {
      hasCanceled_ = true;
    }
  };
};

const initialize = async () => {
  const getImageFilesystemKey = (remoteUri: string) => {
    const [_, fileName] = remoteUri.split("toolbox-talks/");
    return `${cacheDirectory}${fileName}`;
  };

  const filesystemUri = getImageFilesystemKey(uri);

  try {
    // Use the cached image if it exists
    const metadata = await getInfoAsync(filesystemUri);

    if (metadata.exists) {
      console.log("resolve 1");
      return filesystemUri;
    } else {
      const imageObject = await downloadAsync(uri, filesystemUri);
      console.log("resolve 2");
      return imageObject.uri;
    }
    // otherwise download to cache
  } catch (err) {
    console.error("error 3", err);
    return uri;
  }
};

useEffect(() => {
  const cancelable = makeCancelable(initialize());

  cancelable.promise.then(
    fileURI => {
      console.log("resolved");
      setFileUri(fileURI);
    },
    () => {
      // Your logic is such that it's only possible to get here if the promise is cancelled
      console.log("cancelled");
    }
  );

  return () => {
    cancelable.cancel();
  };
}, []);

这样可以确保您仅setFileUri在未取消承诺时才调用(我没有检查 的逻辑makeCancelable)。


推荐阅读