2016年3月12日 星期六

Firebase的第三個練習

下午5:29 Posted by Envisioning U-Commerce Lab

在Firebase寫入多筆資料時,我們的經驗曾有過程式邏輯需要令每一筆資料ID值遞增編碼,而不能讓這些資料的ID值只是毫無關聯的唯一序號,這樣的情況當然不會是我們第一個想到,所以就爬文找到這篇Incremental ID example with Firebase [JavaScript],其可執行程式放JSFiddle,另外也在Github有個規則說明(以後要配合這個程式對Firebase存取權限做相關設定再來看)。 那就讓我們來練習看看如何做出更簡單版本,直接以迴圈執行寫入多筆ID值遞增編碼的資料。
  • 首先,主要概念是在Firebase多增加一個counter資料,只要這個數值是在每筆資料寫入時遞增,而每筆資料ID值就能引用counter數值來做到遞增編碼。這個概念不難懂,就類似我們以往寫程式也常常會宣告一個整體性變數來做counter計數。
  • 不過,因為counter在Firebase上,就代表可能會有存取競態條件(Race Condition)的問題,也就是在同一時間可能有兩個以上的client端發出要求讀寫該數值,而如果不能確保那些讀寫程序不致交錯,就無法保證counter數值的正確性。所以,這個counter的存取就要用到Firebase的transaction()囉,參考這裡介紹Save data as transactionstransaction語法。 
  • 在前述文件中,注意這些說明... When working with data that could be corrupted by concurrent modifications, such as incremental counters, you can use a transaction() operation to update. The update function takes the current state of the data as an argument and returns the new desired state you would like to write. If another client writes to the location before your new value is successfully written, your update function is called again with the new current value, and the write is retried. This repeats until the transaction is accepted or you abort the transaction.
  • 在transaction()語法中安排an optional completion callback function就可以在counter遞增之後緊接著執行將一筆資料寫入的動作,這個callback function裡面的三個參數意義參見Transaction.Handler文章最末表格內的說明。
  • 在callback function裡面主要就是set語法將一筆資料寫入。 
  • 以上概念請參閱放在JSFiddleJSBin程式碼及註解說明,應該就能懂了。這個程式當然也要比照第一個練習在你的Firebase控制台做些設定,然後執行程式後去看Firebase的資料庫就能看到counter計數值停在10,且10筆ID值遞增編碼的資料已寫入。


再來,若要把前述多筆資料讀取出來利用,本來以為弄個簡單的迴圈就可以做到,但因為Javascript非同步執行的特性,使得這件事變複雜了,在使用其他語言習以為常的循序執行概念會被打破
  • 參閱放在JSFiddleJSBin程式碼,這部分有相當多的註解說明,需要靜下心來仔細揣摩才會懂。
  • 先把Firebase參數換成你自己的專案參數,然後執行看看。是否正確把0~9共十筆資料呈現出來。
  • 結果發現第41行的 "document.getElementById('msg').innerHTML += ..." 照理說應該是最先產出結果的,然而卻不是!
  • 接著看51~53行for迴圈的產出,竟然是後發先至,但產出的卻是一堆undefined的資料?
  • 最後在wait2showrecArray()執行for迴圈的產出,總算是正確的了。要關注的重點是在57行以setTimeout執行 wait2showrecArray(),以及在該函式裡面的75行又可能需要再次重複以setTimeout執行 wait2showrecArray(),把這裡搞懂才能正確取得所有資料。






如果只是要ID唯一編碼,那就是另外的概念了,像是Saving Lists of DataJavaScript code for generating Firebase Push IDsThe 2^120 Ways to Ensure Unique Identifiers ...