0

我正在使用 firebase 来存储我的 5 个 jpeg。我需要下载它们并将它们传递给函数以从中检索 EXIF 数据。为了完成这个任务,我制作了如下脚本:

  1. 检查数据库中特定文件夹中有多少文件
  2. 获取每个文件的下载 url
  3. 循环遍历每个 url 并执行函数 wchich 正在从这些 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 []
4

2 回答 2

0

我不确定这是否是问题的原因,但您过度使用了自定义承诺。

据我所知,这个功能:

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())
}
于 2021-10-18T18:23:31.287 回答
0

是的。错误不是由 fetch 本身引起的。我错误地将 url 传递给 fetching 函数。

应该

const result = await getHTML(urls[i]);

代替

const result = await getHTML(urls[i + 1]);
于 2021-10-23T15:59:00.340 回答