我使用firebase来存储我的5个jpeg文件。我需要下载它们并将它们传递给函数以从中检索EXIF数据。为了完成这个任务,我做了下面的脚本:
- 检查数据库 中特定文件夹中有多少个文件
- 获取每个文件的下载url
- 遍历每个url并执行从这些url的 下载文件的函数。
问题是:前四张图片下载正确。最后一个总是没有下载完。
请参阅下面的代码。注意,getHTML1函数与getHTML是冗余的,并给出相同的结果。我只是尝试了不同的方法。
TLDR:如何使fetch等待最后一个文件被完全下载?
import {
getStorage,
ref,
listAll,
getDownloadURL
} from "firebase/storage";
const storage = getStorage();
const listRef = ref(storage, 'images');
const firebaseDownloadHandler = async() => {
function getHTML1(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('get', url);
xhr.responseType = 'blob';
xhr.onload = function() {
var status = xhr.status;
if (status === 200) {
let blob = new Blob([xhr.response], {
type: 'image/jpeg'
})
console.log(xhr.response);
resolve(blob);
} else {
reject(status);
}
};
xhr.send();
});
}
function getHTML(url) {
return new Promise(async function(resolve, reject) {
await fetch(url, {
method: 'GET',
type: 'image/jpeg'
})
.then(res => res.blob())
.then(blob => {
resolve(blob)
});
})
}
const res = await listAll(listRef);
const requests = res.items.map(itemRef => getDownloadURL(itemRef))
const urls = await Promise.all(requests);
const processArray = async() => {
console.log(urls);
const finalResult = [];
return new Promise(async function(resolve, reject) {
for (let i = 0; i < urls.length; i++) {
const result = await getHTML(urls[i + 1]);
finalResult.push(result);
if (finalResult.length === urls.length) {
resolve(finalResult);
}
}
})
};
const downloaded = await processArray();
return await downloaded;
}
export default firebaseDownloadHandler;
结果:
20:06:11.499
Array(5) [ "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…025.jpg?alt=media&token=8ecbfc6d-07ed-4205-9599-a6e36dd444ed", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…028.jpg?alt=media&token=06a422fa-64f2-482f-9f63-c39aaf1d9354", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…855.jpg?alt=media&token=6ae03b2c-bd82-49fc-bcb6-0de0683e7d50", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…402.jpg?alt=media&token=a22ef4dd-7f79-40aa-90df-57ad73b10248", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…646.jpg?alt=media&token=e04958d0-ed2f-44f6-9931-18644ffbe8b8" ]
firebaseDownloadHandler.js:45
20:06:14.882
Array(5) [ Blob, Blob, Blob, Blob, Blob ]
0: Blob { size: 6428869, type: "image/jpeg" }
1: Blob { size: 7402504, type: "image/jpeg" }
2: Blob { size: 2858717, type: "image/jpeg" }
3: Blob { size: 3045876, type: "image/jpeg" }
4: Blob { size: 2278, type: "text/html; charset=utf-8" }
length: 5
<prototype>: Array []
我不确定这是否是问题的原因,但是您过度使用自定义承诺。
在我看来,这个函数:
function getHTML(url) {
return new Promise(async function(resolve, reject) {
await fetch(url, {
method: 'GET',
type: 'image/jpeg'
})
.then(res => res.blob())
.then(blob => {
resolve(blob)
});
})
}
可以在不改变功能的情况下缩短为:
function getHTML(url) {
return fetch(url, {
method: 'GET',
type: 'image/jpeg'
})
.then(res => res.blob())
}
是的。错误不是由fetch本身引起的。我错误地将url传递给抓取函数。
应该
const result = await getHTML(urls[i]);
不是
const result = await getHTML(urls[i + 1]);