我正在使用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);
});
但是现在我正在尝试加载页面中的所有图像,所以我创建了一个带有文件名的Javascript数组变量(用PHP加载),就像这样:
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];
}
}
});
答案 0 :(得分:1)
获取下载URL是异步请求(promises),你执行下一个循环周期而不让前面的循环完成,因此只有最后一个完全执行。
我建议你采取不同的方法。
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];
}
});
答案 1 :(得分:1)
这里的问题是你在循环中使用异步函数,你应该用这种方式使用自包装函数:
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
值