Javascript 卸载组件时,如何取消React中的重复承诺(递归函数)?

Javascript 卸载组件时,如何取消React中的重复承诺(递归函数)?,javascript,reactjs,react-native,promise,cancellation,Javascript,Reactjs,React Native,Promise,Cancellation,大家好 我使用的是React Native,我想添加一些功能,用户可以将多个文件导入到我的应用程序中,用户可以随时取消导入进度 但是,当用户导入这些文件时,我想逐一导入它们,告诉用户哪些文件已成功导入,哪些文件尚未导入 这对我来说很重要,因为我想告诉用户有多少已选择的文件已成功导入,并且在导入文件时,这对于将每个文件显示到UI非常有用,这要求我使用递归函数 问题是我不知道如何取消使用递归函数的承诺,它不起作用,我认为它只是取消树顶部的承诺,而不是所有执行的承诺。此外,如果可能的话,我不想使用任何

大家好

我使用的是
React Native
,我想添加一些功能,用户可以将多个文件导入到我的应用程序中,用户可以随时取消导入进度

但是,当用户导入这些文件时,我想逐一导入它们,告诉用户哪些文件已成功导入,哪些文件尚未导入

这对我来说很重要,因为我想告诉用户有多少已选择的文件已成功导入,并且在导入文件时,这对于将每个文件显示到UI非常有用,这要求我使用
递归函数

问题是我不知道如何取消使用
递归函数的
承诺
,它不起作用,我认为它只是取消树顶部的
承诺
,而不是所有执行的承诺。此外,如果可能的话,我不想使用任何DEP/软件包有什么想法吗?

核心工具

使用真实设备
小米红米1S 4.4 Kitkat

“react”:“16.13.1”,
“反应本机”:“0.63.3”,
代码示例

importFiles.js

从“rn fetch blob”导入RNFetchBlob;
从“@react native community/CameraRoll”导入CameraRoll;
从“lodash”进口;
const fs=RNFetchBlob.fs;
/**
*导入目录目标
*/
const dest=`${fs.dirs.SDCardDir}/VEGA/.src/`;
/**
*用于告诉函数要运行哪个索引的增量索引
*/
设i=0;
/**
*使用一些加密将文件导入此应用
*@param{object}config
*@param{string}config.albumId
*@param{[{
*uri:string,
*mimeType:string,
*相册名称:string,
*时间戳:数字,
*选择:布尔,
*}]}config.files
*@param{'fake'|'real'=}config.encryptionMode
*/
const importFiles=config=>{
返回新承诺(异步(解析、拒绝)=>{
const{albumId,files,encryptionMode}=config;
if(u.isEmpty(文件)| |!uu.isArray(文件)){
拒绝(“无效文件”);
返回;
}
常量文件=文件[i];
/**
*这意味着当文件“未定义”时就完成了
*/
如果(!文件){
解决();
返回;
}
常量uri=file.uri.replace('file://','';
试一试{
/**
*假加密
*
*它很快,但并不完全安全
*/
如果(!encryptionMode | | encryptionMode==='fake'){
const md5=await fs.hash(uri,'md5');
const importedFileUri=`${dest}.${md5}.xml`;
/**
*待办事项:
**可取消测试
*/
等待fs.readFile(uri,'base64');
//等待fs.mv(uri,importedFileUri);
//等待CameraRoll.deletePhotos([uri]);
/**
*如果成功导入此文件,则继续导入
*“未定义”之前的下一个索引
*/
i++;
}
/**
*真正的加密
*
*它很慢,但完全安全
*/
如果(encryptionMode==='real'){
}
等待导入文件({files,encryptionMode});
解决();
}捕获(错误){
拒绝(错误);
}
});
};
导出默认导入文件;
FileImporter.js(如何使用
makeCancelable
方法

import React,{useffect}来自“React”;
从“react native”导入{View,Alert};
从“../components/Helper”导入{container,TopNavigation,Text};
从'react redux'导入{connect};
从“../utils”导入utils;
const makeCancelable=承诺=>{
让hasu=false;
const wrappedPromise=新承诺((解决、拒绝)=>{
我保证,那么(
val=>(hasCancelled_2;reject({isCanceled:true}):resolve(val)),
error=>(hasCancelled_10;reject({isCanceled:true}):reject(error)),
);
});
返回{
承诺:wrappedPromise,
取消{
has=true;
},
};
};
const FileImporter=props=>{
const{userGalleryFiles}=props;
useffect(()=>{
props.navigation.addListener('beforeRemove',e=>{
e、 预防默认值();
警惕,警惕(
“取消?”,
“确实要取消此操作吗?”,
[
{文本:'否',按:()=>{},
{
文本:“是!”,
onPress:()=>props.navigation.dispatch(e.data.action),
},
],
{可取消:true},
);
});
(异步()=>{
const selectedFiles=userGalleryFiles.filter(
file=>file.isSelected===true,
);
试一试{
等待makeCancelable(utils.importFiles({files:selectedFiles})).promise;
安慰。警告(“哦,上帝!!!”);
}捕获(错误){
控制台错误(error);
}
return()=>makeCancelable().cancel();
})();
}, []);
返回(
0/20
);
};
常量mapStateToProps=({userGalleryFiles})=>({userGalleryFiles});
导出默认连接(MapStateTops)(文件导入器);
预期结果

卸载
FileImporter.js
时可以取消
importFiles.js

实际结果

importFiles.js
即使已卸载
FileImporter.js
,使用自定义承诺()您可以执行以下操作():

从“c-promise2”导入{CPromise,CanceledError};
const delay=(ms,v)=>新承诺((resolve)=>setTimeout(resolve,ms,v));
常量导入文件=异步(文件)=>{
返回延迟(1000,文件);//模拟读取任务
};
函数导入文件(文件){
返回CPromise.from(函数*(){
for(设i=0;iimport { CPromise, CanceledError } from "c-promise2";

const delay = (ms, v) => new Promise((resolve) => setTimeout(resolve, ms, v));

const importFile = async (file) => {
  return delay(1000, file); // simulate reading task
};

function importFiles(files) {
  return CPromise.from(function* () {
    for (let i = 0; i < files.length; i++) {
      try {
        yield importFile(files[i]);
      } catch (err) {// optionally
        CanceledError.rethrow(err);
        console.log(`internal error`, err);
        // handle file reading errors here if you need
        // for example if you want to skip the unreadable file
        // otherwise don't use try-catch block here
      }
    }
  }).innerWeight(files.length);
}

const promise = importFiles([
  "file1.txt",
  "file2.txt",
  "file3.txt",
  "file4.txt"
])
  .progress((value) => {
    console.log(`Progress [${(value * 100).toFixed(1)}%]`);
    // update your progress bar value
  })
  .then(
    (files) => console.log(`Files: `, files),
    (err) => console.warn(`Fail: ${err}`)
  );

setTimeout(() => promise.cancel(), 3500); // cancel the import sequence