在卸载时取消承诺内的多个承诺?

您好,自从收到警告以来,我想取消卸载承诺,

警告:无法对已卸载的组件执行 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();

  };

}, []);

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


三国纷争
浏览 133回答 1
1回答

不负相思意

您正在取消承诺,但您并没有取消 axios 调用或在它之后发生的任何逻辑initialize()。因此,虽然控制台确实不会 print&nbsp;resolved,但setFileUri无论如何都会被调用,这会导致您的问题。解决方案可能如下所示(未经测试):const makeCancelable = (promise: Promise<void>) => {&nbsp; let hasCanceled_ = false;&nbsp; const wrappedPromise = new Promise((resolve, reject) => {&nbsp; &nbsp; promise.then(&nbsp; &nbsp; &nbsp; val => (hasCanceled_ ? reject({ isCanceled: true }) : resolve(val)),&nbsp; &nbsp; &nbsp; error => (hasCanceled_ ? reject({ isCanceled: true }) : reject(error))&nbsp; &nbsp; );&nbsp; });&nbsp; return {&nbsp; &nbsp; promise: wrappedPromise,&nbsp; &nbsp; cancel() {&nbsp; &nbsp; &nbsp; hasCanceled_ = true;&nbsp; &nbsp; }&nbsp; };};const initialize = async () => {&nbsp; const getImageFilesystemKey = (remoteUri: string) => {&nbsp; &nbsp; const [_, fileName] = remoteUri.split("toolbox-talks/");&nbsp; &nbsp; return `${cacheDirectory}${fileName}`;&nbsp; };&nbsp; const filesystemUri = getImageFilesystemKey(uri);&nbsp; try {&nbsp; &nbsp; // Use the cached image if it exists&nbsp; &nbsp; const metadata = await getInfoAsync(filesystemUri);&nbsp; &nbsp; if (metadata.exists) {&nbsp; &nbsp; &nbsp; console.log("resolve 1");&nbsp; &nbsp; &nbsp; return filesystemUri;&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; const imageObject = await downloadAsync(uri, filesystemUri);&nbsp; &nbsp; &nbsp; console.log("resolve 2");&nbsp; &nbsp; &nbsp; return imageObject.uri;&nbsp; &nbsp; }&nbsp; &nbsp; // otherwise download to cache&nbsp; } catch (err) {&nbsp; &nbsp; console.error("error 3", err);&nbsp; &nbsp; return uri;&nbsp; }};useEffect(() => {&nbsp; const cancelable = makeCancelable(initialize());&nbsp; cancelable.promise.then(&nbsp; &nbsp; fileURI => {&nbsp; &nbsp; &nbsp; console.log("resolved");&nbsp; &nbsp; &nbsp; setFileUri(fileURI);&nbsp; &nbsp; },&nbsp; &nbsp; () => {&nbsp; &nbsp; &nbsp; // Your logic is such that it's only possible to get here if the promise is cancelled&nbsp; &nbsp; &nbsp; console.log("cancelled");&nbsp; &nbsp; }&nbsp; );&nbsp; return () => {&nbsp; &nbsp; cancelable.cancel();&nbsp; };}, []);这确保了只有setFileUri在promise没有取消的情况下你才会调用(我没有检查逻辑makeCancelable)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript