简体   繁体   English

Firebase 中的递归错误太多

[英]Too much recursion error in Firebase

I have a function in my global scope that listens for values on a FB ref.我的全局范围中有一个函数可以侦听 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 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); (如您所见,由于某种原因,同一个帐户被反复授予积分。我希望它只在 upVote 上获得积分);

It continues with..它继续与..

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

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.我猜 updateCredits 函数正在触发 upVoteRef 监听的事件,它依次调用 updateCredits 函数并变成循环。 I don't know how to avoid this.我不知道如何避免这种情况。 Any ideas?有任何想法吗?

Solution解决方案

You could do你可以做

userRef.once('value').then(function(snapshot){

instead of代替

userRef.on('value', function(snapshot){  

Explanation解释

What on('value') does is that it fires once to fetch all the data at that path, and then fires again every time that data on that path changes . on('value') 的作用是它触发一次以获取该路径上的所有数据,然后每次该路径上的数据更改时再次触发。

Since you update the data on the same path in the callback with由于您在回调中更新相同路径上的数据

userRef.update({credits: updatedCredits});

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.该路径上的数据发生变化并且原始事件(usersRef 上的.value)再次触发,这反过来触发您的回调,您再次更新值 which .... 等等。 This is an infinite loop which causes your error.这是一个无限循环,会导致您的错误。

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如果您只想在有人跑步时添加 ANTE

updateCredits(voterID.val()); 

Then you want to read the data at userRef only once and not actively observe that path.然后您只想读取 userRef 处的数据一次,而不是主动观察该路径。 Hence, .once instead of .on因此,.once 而不是 .on

See Read data once - Firebase Documentation请参阅读取数据一次 - Firebase 文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM