Извлеките, не дожидаясь полной загрузки файла с firebase

# #javascript #firebase #fetch #blob

Вопрос:

Я использую firebase для хранения своих 5 jpeg-файлов. Мне нужно загрузить их и передать в функцию для извлечения из них данных EXIF. Для достижения этой цели, таш, я сделал следующий сценарий, который:

  1. проверка количества файлов в определенной папке базы данных
  2. получение URL-адресов для загрузки каждого файла
  3. просматривая каждый 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]);