基于值侦听器的Firebase有时会触发两次,回调的第一次调用具有它在数据库中的实际值,但偶尔还会有第二次调用,该调用无缘无故地为空值。
我已经通过一些技巧解决了这个问题,但是我只是想知道这是否是预期的Firebase行为,或者我发生了一些错误。
//threshold value is set dynamicly depending on another query
queryNewPosts = postRef.orderByKey().startAt(threshold)
listenerNewItems = queryNewItems.on("child_added", function(snapshot){
let postRef = db.ref(`items/${place}/${snapshot.key}`)
postRef.on("value", function(postSnap){
//!!This sometimes fires twice and postSnap.val() == null
//postSnap.val() is null when its path has a value in the database
})
})
包括两次根据请求对数据库进行写的情况
//client side
let postsRef = db.ref(`items/${place}`)
let postKey = postsRef.push().key
postsRef.child(postKey).set({
id: postKey,
timestamp: firebase.database.ServerValue.TIMESTAMP,
content: post.content.toLowerCase(),
user: uid,
commentCount: 0,
vote: 0
})
云函数代码,可能是空写发生的地方
如果postId以某种方式最终为空,则事务可能会将null写入错误的路径
exports.updatePostVote = functions.database
.ref('/postVotes/{place}/{postId}/{uid}').onWrite((change, context) =>{
if (change.before.exists() && !change.after.exists())
return null;
let afterValue = change.after.val()
let beforeValue = change.before.val()
if (afterValue === beforeValue)
return null;
const postId = context.params.postId
const place = context.params.place
const uid = context.params.uid
const dif = afterValue - (beforeValue || 0)
const ref = admin.database().ref(`/posts/${university}/${postId}`)
return ref.child('vote').transaction(function(current) {
return (current || 0) + dif;
});
});