iT邦幫忙

0

firebase如何將擷取的資料存入本地端變數

如題,小弟想要從firebase抓取count這欄的值並傳入變數使用,但發現spots_count離開firebase定義函數後會變空值

count_spots=""; //set count_spots as a global variable
firebase.auth().onAuthStateChanged(function(user) {
var loginUser = user;
var ref = firebase.database().ref('users/'+loginUser.uid+'/myfav_spots');

ref.on('value',function(snapshot){
count_spots = snapshot.val().count;

});
});

for (var i = 1; i < count_spots; i++) {
....

1 個回答

1
froce
iT邦新手 3 級 ‧ 2017-10-10 23:35:50
最佳解答

寫程式,變數的生命週期要懂啊。
你這樣寫,spots_count只會活在你這個function裡面。
解決法:
把spots_count宣告在外面,成為全域變數(要注意使用時機)

var spots_count = "";

firebase.auth().onAuthStateChanged(function(user) {
var loginUser = user;
var ref = firebase.database().ref('users/'+loginUser.uid+'/myfav_spots');

ref.on('value',function(snapshot){
spots_count = snapshot.val().count;
console.log("count="+snapshot.val().count);

});
});
看更多先前的回應...收起先前的回應...

宣告成全域變數取得的值還是空值,您可以試試看

froce iT邦新手 3 級 ‧ 2017-10-10 23:57:39 檢舉

firebase這東西我又沒用到,怎麼幫你測...
頂多幫你寫個小型測試碼。
全域變數:

var test = "";
function testfunction(){
    test = "1";
}

testfunction();
console.log(test);

這樣在終端機會出現"1"。

寫在函式裡:

function testfunction(){
    var test = "1";
}

testfunction();
console.log(test);

終端機出現的是"test未定義"。
你原來的程式碼是第二種,一定不會成功,因為這變數只活在函式裡。

要不然就是函式多個return,把snapshot.val().count傳回,然後用另外一個變數去接。

froce iT邦新手 3 級 ‧ 2017-10-11 13:23:30 檢舉

你這樣寫當然接不到啦...早點把後面的丟出來我才知道你想要怎麼做。
onAuthStateChanged()是事件,是非同步的,你的function是在事件發生後才執行的,並不是網頁載入時執行的。

你的for迴圈則是網頁一開始完全載入就執行了,這樣當然接不到值。

firebase.auth().onAuthStateChanged(function(user) {
var loginUser = user;
var ref = firebase.database().ref('users/'+loginUser.uid+'/myfav_spots');

ref.on('value',function(snapshot){
var count_spots = snapshot.val().count;
   
   for (var i = 1; i < count_spots; i++) {
....
});
});

把for迴圈放進function裡就行了,要不然就是想辦法去關掉,或是用promise去解決。
http://www.oxxostudio.tw/articles/201706/javascript-promise-settimeout.html

好的,我試試看用promise解決:)

好的,我試試看用promise解決:)

這段程式碼用意是要抓取資料筆數,將筆數存到變數裏頭供迴圈使用。

1.for迴圈放進function裡
-> 迴圈內容css無法正常運作。

2.關掉async
我有查了一下,firebase本身是非同步更新,我在stack overflow搜尋網友的答案是無法更新改同步更新。

3.用promise去解決
->小弟對promise這塊不熟,如果要更改成promise要如何更改?大概方向,感謝回覆。

froce iT邦新手 3 級 ‧ 2017-10-11 19:23:16 檢舉

你要不要把迴圈內CSS整段code丟出來我看看?

<script type="text/javascript">
count_spots = "";
function delay(){
return new Promise (function (resolve,reject){
setTimeout(function(){
firebase.auth().onAuthStateChanged(function(user) {
var loginUser = user;
var ref = firebase.database().ref('users/'+loginUser.uid+'/myfav_spots');

ref.on('value',function(snapshot){
resolve (snapshot.val().count);

});
});
},5000)
});
}

delay().then(function(value){
console.log(value);
count_spots = value;
}).catch(function(error){
console.log(error);
}); 

for (var i = 1; i < count_spots; i++){
document.write("<div class='hotel-rooms'>");
document.write("<div class='hotel-left'>");
document.write("<a href='#'>");
document.write("<span aria-hidden='true' class='glyphicon glyphicon-map-marker' id='spot_name"+ i + "'>");
document.write("</span>");
document.write("<img alt='' id='hotel_img src='images/star2.png'>");
document.write("</a>");

document.write("<p id='added_time"+ i + "'>");
document.write("</p>");

document.write("<div class='hotel-left-grids'>");
document.write("<div class='hotel-left-one'>");
document.write("<img alt='' src='images/h1.jpg'>"); 
document.write("<span class='sale-box'>");

document.write("<span class='sale-label' id='spot_class"+ i + "'>");
document.write("</span>");
document.write("</span>");
document.write("</div>");




document.write("<div class='clearfix'>");
document.write("</div>");
document.write("</div>");
document.write("</div>");


document.write("<div class='hotel-right text-right'>");

document.write("<a class='seat-button hotel' style='background:#f95252'><i class='fa fa-heart' style='color:white;'></i>");
document.write("<a class='seat-button hotel' >其他留言");
document.write("</a>"); 

document.write("</div>");


document.write("<div class='clearfix'>");
document.write("</div>");
document.write("</div>");



}

</script>

這是完整script

我在想回圈部分會先跑,不如何先設定TimeOut

資料有跑出來,但外觀大走鐘XD

froce iT邦新手 3 級 ‧ 2017-10-12 08:42:27 檢舉

你瀏覽器是用Chrome?看起來不是code的問題。

沒錯,我是用chrome開

測試三個瀏覽器結果都是一樣的

頁面刷新後,只顯示document.write內的內容

froce iT邦新手 3 級 ‧ 2017-10-12 20:20:58 檢舉
document.write("<a class='seat-button hotel' style='background:#f95252'><i class='fa fa-heart' style='color:white;'></i>");

這句加個

</a>

看看。

感覺是html結構的問題。
你應該試試看先不要插入這麼複雜的html結構。
https://stackoverflow.com/questions/11471151/css-not-being-applied-to-html-elements-created-with-jquery-append

froce iT邦新手 3 級 ‧ 2017-10-12 20:28:28 檢舉
document.write("<img alt='' id='hotel_img src='images/star2.png'>");

這行id少一個「'」。

http://validator.w3.org/check
這個可以幫你分析html結構。

froce iT邦新手 3 級 ‧ 2017-10-12 20:43:10 檢舉

然後這是我的習慣。
像這種比較複雜的HTML,我會使用一個變數去存。

var html = '<div class="...">' +
                        '<a></a>' +
                        ... +
                    '</div>';
document.write(html);

這樣應該會比較清楚,寫的字數也比較少。
另外也建議縮排弄好一點。

已經用好了,謝謝你耐心回覆。

我是使用這個網站整理排版
網址:https://dirtymarkup.com/

froce iT邦新手 3 級 ‧ 2017-10-12 22:54:36 檢舉

所以問題確定是怎樣?

froce iT邦新手 3 級 ‧ 2017-10-12 22:54:39 檢舉

所以問題確定是怎樣?

我稍微調整讀取順序,謝謝你喔:)

我要發表回答

立即登入回答