问题描述
我的全局范围内有一个函数可以侦听FB ref上的值。
I have a function in my global scope that listens for values on a FB ref.
function updateCredits(userID){
var userRef = database.ref('users/' + userID);
userRef.on('value', function(snapshot){
var userCredits = snapshot.val().credits;
console.log(userCredits);
console.log('account: ' + userID + " has " + userCredits + " credits");
var updatedCredits = userCredits + ANTE;
userRef.update({credits: updatedCredits});
console.log("now it has " + updatedCredits + ANTE);
});
}
articlesRef.on('child_added', function(data) {
var upVoteRef = database.ref('articles/' + data.key + '/upVotes/');
try {
var upVotersRef = database.ref('articles/' + data.key + '/upVoters/');
upVoteRef.on('value', function(childData){
upVotersRef.on('value', function(voterData){
var voterKeys = Object.keys(voterData.val());
for (var i=0; i<voterKeys.length; i++){
upVotersRef.child(voterKeys[i]).on('value', function(voterID){
console.log("trying with voter ID " + voterID.val());
updateCredits(voterID.val());
});
}
});
});
} catch(err){
console.log(err.message);
}
var downVoteRef = database.ref('articles/' + data.key + '/downVotes/');
downVoteRef.on('value', function(childData){
console.log(childData.val());
});
});
不知何故,当我加载页面时,这个功能显然被称为数百或数千次。我把它记录到控制台:
Somehow, when I load the page, this function is apparently called hundreds or thousands of times. I get this logged to the console:
account: HMHZ8Ga3UGhc2wSczHDuFL82FB02 has 1328.6999999997329 credits app.js:25:9
1328.6999999997329 app.js:24:9
1328.8999999997327 app.js:24:9
account: HMHZ8Ga3UGhc2wSczHDuFL82FB02 has 1328.8999999997327 credits app.js:25:9
1328.8999999997327 app.js:24:9
account: HMHZ8Ga3UGhc2wSczHDuFL82FB02 has 1328.8999999997327 credits app.js:25:9
1328.9999999997326 app.js:24:9
account: HMHZ8Ga3UGhc2wSczHDuFL82FB02 has 1328.9999999997326 credits app.js:25:9
1328.9999999997326 app.js:24:9
account: HMHZ8Ga3UGhc2wSczHDuFL82FB02 has 1328.9999999997326 credits ...
(As你可以看到,由于某种原因,同一个帐户被重复给予信用。我希望它只能在upVote上获得积分);
(As you can see, for some reason the same account is being repeatedly given credits. I want it to only be given credits on an upVote);
它继续...
now it has 1330.09999999973160.1 app.js:28:9
now it has 1329.99999999973170.1 app.js:28:9
now it has 1329.89999999973180.1 app.js:28:9
now it has 1329.79999999973190.1 app.js:28:9
now it has 1329.6999999997320.1 app.js:28:9
...
最后,问题是:
...and finally, the problem:
too much recursion[Learn More] firebase.js:293:781
我想updateCredits函数正在触发upVoteRef正在监听的事件,而upVoteRef又调用updateCredits函数并变为循环。我不知道如何避免这种情况。有什么想法?
I guess the updateCredits function is triggering an event being listened to by the upVoteRef, which in turns calls the updateCredits function and becomes circular. I don't know how to avoid this. Any ideas?
推荐答案
解决方案
你可以做
Solution
You could do
userRef.once('value').then(function(snapshot){
而不是
userRef.on('value', function(snapshot){
说明
('值')的作用是,它会触发一次以获取该路径上的所有数据,然后每次该路径上的数据发生变化时再次触发。
由于您使用
userRef.update({credits: updatedCredits});
该路径上的数据发生变化,原始事件(usersRef上的.value)再次触发,反过来触发你的回调,你再次更新......等等的值。这是一个无限循环,导致你的错误。
The data on that path changes and the original event (.value on usersRef) fires again, which in turn fires your callback and you again update the value which .... and so on. This is an infinite loop which causes your error.
To避免这种情况,你可以做几个取决于你想要实现的目标。如果您只想在某人运行时添加ANTE
To avoid this, you can do several things depending on what you are trying to achieve. If you only want to add ANTE when somebody runs
updateCredits(voterID.val());
然后,您只想在userRef上读取一次数据,而不是主动观察该路径。因此,.once而不是.on
Then you want to read the data at userRef only once and not actively observe that path. Hence, .once instead of .on
请参阅
这篇关于Firebase中的递归错误太多的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!