这个块的快速解释:我有一个files
对象,这是我上传的所有文件,然后我有一个signedUrls
对象,其中包含来自早期S3函数的所有签名URL。对象具有匹配的索引。
第一个axios.put
上传文件,第二个axios.post
将文件密钥保存到我的数据库。 (除非上传成功,否则我不想将其保存到我的数据库中,因此axios.post
在回调中的位置。)
文件上传得很好,但fileId
没有正确循环,通常一遍又一遍地保存相同的fileId
。即,如果我上传了五个文件,它们将上传到S3,但它们在我的数据库中都具有相同的ID。想法为什么会这样?
fileIds = {"1": "someFileId", "2": "someOtherId" }
for (let i = 0; i < files.length; i++) {
axios.put(signedUrls[i], files[i], config).then(res => {
axios.post('https://myapi.com/add-file', {
fileId: fileIds[i]
}).then(res => {
// success
});
这是因为你在同步for
循环中进行异步调用。
到调用post
请求时,您的循环已经完成。
您可以使用Promise.all
来解决此问题:
const promises = files.map((file, i) => {
// create a new promise with correct index, but don't call it yet
return new Promise((resolve, reject) => {
return axios.put(signedUrls[i], file, config)
.then(res => {
return axios.post('https://myapi.com/add-file', {
fileId: fileIds[i]
}).then(res => {
resolve(res)
// todo: also handle errors here
})
})
})
})
// actually invoke your calls here
Promise.all(promises).then(res => /* success */ )
从本质上讲,你要做的是同步创建你的promise调用(但实际上还没有调用它们),这样你就可以使用正确的索引,然后你将使用Promise.all
实际调用promises数组。
问题是i
在你的.post
部分中绑定了相同的值。
要解决此问题 - 您可以使用自执行匿名函数。
像这样:
for (let i = 0; i < files.length; i++) {
(function(i) {
axios.put(signedUrls[i], files[i], config).then(res => {
axios.post('https://myapi.com/add-file', {
fileId: fileIds[i]
}).then(res => {
// success
});
})(i);
}