我正在实现一个选择和下载多个文档的功能。
首先,我构建了一个对象数组,其中包含每个选定文档的名称和指向其位置的链接。
getAllSelectedUrls = () => {
const { selectedFiles } = this.state;
const urls = [];
selectedFiles.forEach((file) => {
this.returnFileUrl(file.id).then(res => res.json()).then((data) => {
urls.push({ fileName: file.name, url: data.content_path });
});
});
return urls;
}
returnFileUrl()
是一个异步API调用,用于通过ID:获取文件的链接
returnFileUrl = async (fileId) => {
try {
const resp = await fetch(`/file?fileId=${fileId}`);
return resp;
} catch (err) {
console.log(err);
}
}
我认为通过更新.then
方法中的urls
数组,我可以确保每个url
在返回时都得到解析。
当我调用getAllSelectedUrls()
时,我可以在控制台中记录阵列,并填充所有数据。然而,我无法对其进行迭代或通过索引访问任何对象,可能是因为此时数据尚未解析。
使用Promise.all((
getAllSelectedUrls = () => {
const { selectedFiles } = this.state;
return Promise.all(selectedFiles.map(file => {
return this.returnFileUrl(file.id)
.then(res => res.json())
.then(data => ({ fileName: file.name, url: data.content_path }))
}))
.then(urls => {
//do whatever you need to do with the urls array
})
.catch(e => console.log(e))
}
同意@Bergi的意见,return
不会等到异步调用完成。它立即返回一个空数组。但是,如果urls
数组已完全填充,则可以对每个解析进行检查。如果是,请将变量存储在某个位置,例如使用setState
。
或者只需将urls
数组移动到该状态,并通过每次解析将url
简单地推到该状态。
selectedFiles.forEach((file) => {
this.returnFileUrl(file.id).then(res => res.json()).then((data) => {
urls.push({ fileName: file.name, url: data.content_path });
if (urls.length === selectedFiles.length) {
this.setState({ urls });
}
});
});
试试这个:
(已编辑(
getAllSelectedUrls = async () => {
const { selectedFiles } = this.state;
const urls = [];
for (let i = 0; i < selectedFiles.length; i++) {
const file = selectedFiles[i];
res = await this.returnFileUrl(file.id);
data = await res.json();
urls.push({ fileName: file.name, url: data.content_path });
}
return urls;
}
像这样,该函数将在所有承诺都得到解决并推送url 后返回