2017-07-20 132 views
2

我正在开始使用Firebase存储网的第一步,并承认Javascript不是我的专业。从Firebase存储下载多个图像

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

这里是(用PHP生成)的HTML的一个简单的例子:

<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> 

我已经添加了火力地堡API按照https://firebase.google.com/docs/web/setup此页的说明并初始化它像这样:

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]; 
      } 
     } 
}); 

回答

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

+1

谢谢Devid!你的解释非常好,我明白我做错了什么。我会接受你的回答,但也留下我的解决方案。 – Guybrush

0

的读取下载网址是异步请求(承诺),并在执行下一个循环周期而不让以前的完成,因此只执行最后一个完全。

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

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]; 
    } 
}); 
+0

谢谢阿南德,但你肯定这项工作?我不能让它工作,即使在删除循环并使用静态值时... – Guybrush

+0

哦,并且控制台日志中没有错误消息... – Guybrush