2017-07-20 161 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