【问题标题】:Download multiple images from Firebase Storage从 Firebase 存储下载多个图像
【发布时间】:2017-07-20 15:22:15
【问题描述】:

我正在迈出 Firebase Storage Web 的第一步,并承认 Javascript 也不是我的专长。

我有一个包含人员姓名列表的网页 (PHP),我想在姓名旁边显示他们的相应照片。图片保存在 Firebase 存储文件夹中。

这是一个简单的 html 示例(使用 PHP 生成):

<div id="people_list">
    <div class="list_row">
        <div class="photo">
            <img id="photo1" src="images/stdphoto.png" width="50" height="50">
        </div>
        <div class="name">
            People Name 1
        </div>
    </div>
    <div class="list_row">
        <div class="photo">
            <img id="photo2" src="images/stdphoto.png" width="50" height="50">
        </div>
        <div class="name">
            People Name 2
        </div>
    </div>
</div>

我已经按照本页 https://firebase.google.com/docs/web/setup 中的说明添加了 Firebase API,并像这样初始化它:

firebase.initializeApp(config);
firebase.auth().signInAnonymously(); // Ignoring security for now

这是我加载一张照片的代码。效果很好!

var storage = firebase.storage();
var refPath = storage.ref('photos/johnnydepp.jpg');
refPath.getDownloadURL().then(function(url) {
    document.getElementById('photo1').src = url;
}).catch(function(error) {
    console.log(error);
});

但现在我正在尝试加载页面中的所有图像,所以我创建了一个带有文件名(用 PHP 加载)的 Javascript 数组变量,并且这样做:

var photos = ["johnnydepp", "jimcarrey", "emmawatson"];

var photoId = 0;
var refPath = null;
var storage = firebase.storage();
for (var i = 0; i <= photos.length - 1; i++) {
    photoId = i + 1;
    refPath = storage.ref('photos/' + photos[i] + '.jpg');
    refPath.getDownloadURL().then(function(url) {
        document.getElementById('photo' + photoId).src = url;
    }).catch(function(error) {
        console.log(error);
    });
}

我不知道为什么,但只加载列表中的最后一张照片。 Javascript 控制台中没有错误。

拜托,你知道我做错了什么吗?谢谢!

编辑(我的解决方案):

const promises = [];

photos.forEach(val => {
    const promise = firebase.storage()
        .ref('photos/' + val + '.jpg')
        .getDownloadURL()
        .catch(err => {
            console.log('error', err);
            return "";
        })
        .then(fileUrl => {
            return fileUrl;
        });
    promises.push(promise);
});

Promise.all(promises)
    .catch(err => {
        console.log('error', err);
    })
    .then(urls => {
        for (var i = 0; i <= urls.length - 1; i++) {
            if (urls[i] != '') {
                document.getElementById('photo' + (i + 1)).src = urls[i];
            }
        }
});

【问题讨论】:

  • Guybrush Threepwood!

标签: javascript php firebase firebase-storage


【解决方案1】:

获取的下载 url 是异步请求(承诺),您执行下一个循环周期而不让前面的循环完成,因此只有最后一个完全执行。

我建议你采取不同的方法。

var photos = ["johnnydepp", "jimcarrey", "emmawatson"];

var photoId = 0;
var storage = firebase.storage();
var promises = [];
for (var i = 0; i <= photos.length - 1; i++) {
    photoId = i + 1;
    promises.push(storage.ref('photos/' + photos[i] + '.jpg').getDownloadURL());
}

photoId = 0;
Promise.all(promises, data => {
    for (var i = 0; i <= photos.length - 1; i++) {
        photoId = i + 1;
        document.getElementById('photo' + photoId).src = data[i];
    }
});

【讨论】:

  • 谢谢阿南德,但你确定这行得通吗?即使删除循环并使用静态值,我也无法使其工作......
【解决方案2】:

这里的问题是你在循环中使用异步函数,你应该这样使用自包装函数:

for (var i = 0; i <= photos.length - 1; i++) {
    photoId = i + 1;
    refPath = storage.ref('photos/' + photos[i] + '.jpg');
    (function(pid) {
        refPath.getDownloadURL().then(function(url) {
            document.getElementById('photo' + pid).src = url;
        }).catch(function(error) {
            console.log(error);
        });
    })(photoId);
}

您的代码不起作用,因为您在延迟后收到来自 firebase 的值,当您调用 getElemById(photoId) 时,photoId 的值已经更改。您可以在这里看到相同的行为:

for (var i = 0; i <= photos.length - 1; i++) {
    photoId = i + 1;
    setTimeout(function() {
        console.log(photoId);
    }, 1000)
}

自包装函数会创建一个 closure 来保留您的 photoId

【讨论】:

  • 谢谢你!你的解释很好,我明白我做错了什么。我会接受你的回答,但也会在问题中留下我的解决方案。
猜你喜欢
  • 2016-12-28
  • 2017-01-16
  • 2021-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-11
  • 2022-01-02
  • 2017-10-01
相关资源
最近更新 更多