# #javascript #firebase #fetch #blob
Вопрос:
Я использую 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=mediaamp;token=8ecbfc6d-07ed-4205-9599-a6e36dd444ed", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…028.jpg?alt=mediaamp;token=06a422fa-64f2-482f-9f63-c39aaf1d9354", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…855.jpg?alt=mediaamp;token=6ae03b2c-bd82-49fc-bcb6-0de0683e7d50", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…402.jpg?alt=mediaamp;token=a22ef4dd-7f79-40aa-90df-57ad73b10248", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…646.jpg?alt=mediaamp;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 []
Ответ №1:
Я не уверен, что это причина проблемы, но вы злоупотребляете пользовательскими обещаниями.
Насколько я могу судить, эта функция:
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())
}
Комментарии:
1. Верно. Та же функциональность. Я пытаюсь сделать все, чтобы получить это ожидание последнего файла. С этой укороченной функцией ничего не изменилось.
Ответ №2:
Да. Ошибка не вызвана самой выборкой. Я неправильно передал URL-адреса в функцию извлечения.
Должно быть
const result = await getHTML(urls[i]);
Вместо
const result = await getHTML(urls[i 1]);