javascript - 如何编写异步函数
问题描述
我正在做我的第一个反应网站,我需要帮助来编写一个异步 JavaScript 函数。在这里,我将用户输入文件上传到 Firebase 存储,然后向 API 发出发布请求以将数据存储在数据库中。但是,由于 firebase 上传需要一些时间将数据上传到其存储,API 请求发生在上传完成之前,因此数据不会上传到数据库。现在我知道我应该在这里使用 async await 关键字的承诺,但我不知道该怎么做。如果有人可以提供帮助,我将不胜感激。提前致谢!
这是相关的代码片段:
const save = (items) => {
items.forEach((item) => {
const fileName = new Date().getTime() + item.label + item.file.name;
const uploadTask = storage.ref(`/items/${fileName}`).put(item.file);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log("Upload is" + progress + "% done.");
},
(err) => {
console.log(err)
},
() => {
storage.ref("items").child(fileName).getDownloadURL().then((url) => {
setSong((prev) => {
return { ...prev, [item.label]: url };
});
});
}
);
})
console.log(song)
axios.post("songs/create", song);
}
PS:这里的 items 是来自用户的输入文件数组,每个文件都有一个标签,这是 json 文档中属性的命名方式。setSong 是一个 useState 函数。这里 JSON 文档已经包含其他用户输入(不是文件),并且 setSong 方法用于将文件的 firebase URL 附加到它。
解决方案
您必须等待所有文件上传,然后才能调用 API,为此您应该使用Promise.all
等待来解析所有文件:
const save = items => {
Promise.all(
items.map(item => {
return new Promise(resolve => {
const fileName = new Date().getTime() + item.label + item.file.name
const uploadTask = storage.ref(`/items/${fileName}`).put(item.file)
uploadTask.on(
'state_changed',
snapshot => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
console.log('Upload is' + progress + '% done.')
},
err => {
console.log(err)
},
() => {
storage
.ref('items')
.child(fileName)
.getDownloadURL()
.then(url => {
setSong(prev => {
return { ...prev, [item.label]: url }
})
resolve({[item.label]: url})
})
}
)
})
})
).then((res) => {
const song = {}
res.forEach(item => {
return {
...song,
...item
}
})
axios.post('songs/create', song)
})
}