为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

三国纷争 2023-07-20 16:31:16
您好,自从收到警告以来,我想取消卸载承诺,警告:无法对已卸载的组件执行 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();  };}, []);但我仍然在快速按下时收到警告,请帮助我吗?
查看完整描述

1 回答

?
不负相思意

TA贡献1777条经验 获得超10个赞

您正在取消承诺,但您并没有取消 axios 调用或在它之后发生的任何逻辑initialize()。因此,虽然控制台确实不会 print resolved,但setFileUri无论如何都会被调用,这会导致您的问题。

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

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在promise没有取消的情况下你才会调用(我没有检查逻辑makeCancelable)。


查看完整回答
反对 回复 2023-07-20
  • 1 回答
  • 0 关注
  • 123 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信