Javascript 承诺解析时,状态更改意外重置

Javascript 承诺解析时,状态更改意外重置,javascript,reactjs,promise,axios,Javascript,Reactjs,Promise,Axios,我有以下代码: http-common.ts 从“axios”导入axios; 导出默认的axios.create({ baseURL:window.location.origin, 标题:{ “内容类型”:“应用程序/json”, }, }); 类型.ts enum上载状态{ 没有一个 上传, 完成, } 导出默认上载状态; UploadForm.tsx import*as React from'React'; 从“/http common”导入http; 从“./types”导入上载状态

我有以下代码:

http-common.ts

从“axios”导入axios;
导出默认的axios.create({
baseURL:window.location.origin,
标题:{
“内容类型”:“应用程序/json”,
},
});
类型.ts

enum上载状态{
没有一个
上传,
完成,
}
导出默认上载状态;
UploadForm.tsx

import*as React from'React';
从“/http common”导入http;
从“./types”导入上载状态;
类型UploadItem={
档案:档案,
进展:数目,
上传成功:布尔值|未定义,
错误:字符串,
};
const sendUpload=(文件:file,onUploadProgress:(progressEvent:any)=>void)=>{
const formData=new formData();
formData.append('file',file);
返回http.post('/api/uploadFile',formData{
标题:{
“内容类型”:“多部分/表单数据”,
},
onUploadProgress,
});
};
const UploadForm=()=>{
const[fileSelection,setSelection]=useState([]);
const[currUploadStatus,setUploadStatus]=useState(UploadStatus.NONE);
useffect(()=>{
如果(currUploadStatus==UploadStatus.UPLOADING){
常量承诺:承诺[]=[];
//待讨论的问题代码
承诺。一切都解决了(承诺)
。然后(()=>setUploadStatus(UploadStatus.DONE));
}
},[currenuploadstatus]);
const handleFileSelectChange=(事件:React.ChangeEvent)=>{
if(event.target.files!==null){
let newSelection:UploadItem[]=Array.from(event.target.files).map((currFile)=>({
档案:currFile,
进展:0,
上载成功:未定义,
错误:“”,
检查:错误,
}));
if(currUploadStatus==UploadStatus.NONE){
newSelection=newSelection.reduce((currSelection,newsellitem)=>{
如果(
currSelection.every((currSelItem)=>currSelItem.file.name!==newSelItem.file.name)
) {
currSelection.push(新闻精英);
}
返回选择;
},[…选举];
}
选举(新闻选举);
}
};
//代码的其余部分
}
我正在尝试将文件从客户端上载到服务器。
sendUpload
中的第二个参数,
onUploadProgress
是一个函数,返回当前文件上载进度,让我在屏幕上呈现进度条

在我的第一次尝试中,
useffect
实现如下:

useffect(()=>{
如果(currUploadStatus==UploadStatus.UPLOADING){
常量承诺:承诺[]=[];
fileSelection.forEach((currUploadItem)=>{
const promise:promise=sendUpload(
currUploadItem.file,
(事件:任何)=>{
setSelection(()=>fileSelection.map((currMapItem)=>(
currMapItem.file.name==currUploadItem.file.name
? {
…currMapItem,
进度:数学四舍五入((100*event.loaded)/event.total),
}
:currMapItem
)));
},
)
。然后({data})=>{
setSelection(()=>fileSelection.map((currMapItem)=>(
currMapItem.file.name==currUploadItem.file.name
? {
…currMapItem,
uploadSuccess:data.uploadSuccess,
}
:currMapItem
)));
})
.catch((错误)=>{
setSelection(()=>fileSelection.map((currMapItem)=>(
currMapItem.file.name==currUploadItem.file.name
? {
…currMapItem,
错误,
上传成功:false,
}
:currMapItem
)));
});
承诺。推动(承诺);
});
承诺。一切都解决了(承诺)
。然后(()=>setUploadStatus(UploadStatus.DONE));
}
},[currenuploadstatus]);
在上面的
useffect
code中,我观察到当文件被上传时(即
sendUpload(curruloadItem.file,…)
部分),进度被正确更新为
fileSelection
状态。当我调节浏览器时,我可以看到我的进度条随着时间的推移正确地填满

但是,一旦承诺解决了,我进入了
。然后(…)
代码部分,progress值返回到0。在
then(…)
code段中,
uploadSuccess
被正确更新为true,该值被成功保存为状态并保持不变。换句话说,我可以在屏幕上看到上载成功消息,但在达到100%后,我的进度条已重置为0%

在第二次尝试中,我将代码更改为:

useffect(()=>{
如果(currUploadStatus==UploadStatus.UPLOADING){
常量承诺:承诺[]=[];
for(fileSelection.entries()的常量[idx,item]){
const promise:promise=sendUpload(
item.file,
(事件:任何)=>{
const updatedSelection=[…fileSelection];
updatedSelection[idx].progress=Math.round((100*event.loaded)/event.total);
设置选择(更新的选择);
},
)
。然后({data})=>{
const updatedSelection=[…fileSelection];
updatedSelection[idx]。uploadSuccess=data.uploadSuccess;
设置选择(更新的选择);
})
.catch((错误)=>{
const updatedSelection=[…fileSelection];
更新的选择[idx]={
…updatedSelection[idx],
错误,
上传成功:false,
};
设置选择(更新的选择);
});
承诺。推动(承诺);
}
承诺。一切都解决了(承诺)
。然后(()=>setUploadStatus(UploadStatus.DONE));
}
},[currenuploadstatus]);
updatedSelection[idx].progress = Math.round((100 * event.loaded) / event.total);
  useEffect(() => {
    if (currUploadStatus === UploadStatus.UPLOADING) {
      const promises = fileSelection.map(uploadItem =>
        sendUpload(
          uploadItem.file,
          (event: any) => {
            setSelection(currSelection =>
//                       ^^^^^^^^^^^^^
              currSelection.map(item => item.file.name === uploadItem.file.name
                ? {
                  ...item,
                  progress: Math.round((100 * event.loaded) / event.total),
                }
                : item
              )
            );
          },
        )
          .then(({data}) => ({
            uploadSuccess: data.uploadSuccess
          }, error => ({
            error,
            uploadSuccess: false
          })
          .then(result => {
            setSelection(currSelection =>
//                       ^^^^^^^^^^^^^
              currSelection.map(item => item.file.name === uploadItem.file.name
                ? {
                  ...item,
                  ...result,
                }
                : item
              )
            );
          })
      );

      Promise.all(promises)
        .then(() => setUploadStatus(UploadStatus.DONE));
    }
  }, [currUploadStatus]);