Firebase中的递归错误太多

时间:2017-01-17 14:16:35

标签: javascript asynchronous recursion firebase firebase-realtime-database

我的全局范围内有一个函数可以侦听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());

    });


});

不知何故,当我加载页面时,这个功能显然被称为数百或数千次。我把它记录到控制台:

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  ...

(正如你所看到的,由于某种原因,同一个帐户正在重复给予学分。我希望它只能在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

... 最后,问题是:

too much recursion[Learn More]  firebase.js:293:781

我想updateCredits函数正在触发upVoteRef正在侦听的事件,而upVoteRef又调用updateCredits函数并变为循环。我不知道如何避免这种情况。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

解决方案

你可以做到

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

而不是

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

说明

(&#39;值&#39;)的作用是,它会触发一次以获取该路径中的所有数据,然后每次该路径上的数据发生变化时再次触发。

由于您使用

更新回调中相同路径上的数据
userRef.update({credits: updatedCredits});

该路径上的数据发生变化,原始事件(usersRef上的.val)再次触发,这反过来会触发您的回调,并再次更新....等等。这是一个无限循环,导致您的错误。

为了避免这种情况,您可以根据您要实现的目标做几件事。如果您只想在有人跑的时候添加ANTE

updateCredits(voterID.val()); 

然后,您只想在userRef上读取一次数据,而不是主动观察该路径。因此,.once而不是.on

请参阅Read data once - Firebase Documentation