bugfix> firebase > 投稿


こんにちは、上記はfirebaseのリアルタイムデータベースの単純なデータ構造です。ユーザーノードの「スコア」プロパティで更新をリッスンし、階層の上位にある「averageScore」フィールドを更新する単純なクラウド関数に取り組んでいます。

これが私のonWriteコールバックです。

.onWrite((change, context) => {
    if (!change.before.exists() || !change.after.exists()) {
        return null;
    }
    const beforeScore = parseFloat(change.before.val()['score']);
    const afterScore = parseFloat(change.after.val()['score']);
    const userRef = change.after.ref;
    var promises = [
        userRef.parent.parent.child('userCount').once('value'),
        userRef.parent.parent.child('averageScore').once('value')
    ];
    return userRef.transaction(() => {
        return Promise.all(promises).then((snapshots) => {
            const userCount = snapshots[0].val();
            const averageScore = snapshots[1].val();
            const currentAverage = (( ( averageScore * userCount ) - beforeScore + afterScore ) / userCount ).toFixed(2);
            return userRef.parent.parent.child('averageScore').set(currentAverage);
        });
    });
});

userId 1234を更新した場合スコアaverageScore フィールドはこのコードごとに正しく更新されます。ただし、ユーザーIDノード1234全体は削除済み この更新後。これは非常に頭を悩ませるものであり、私が間違っているかもしれないことについてコミュニティから何らかの洞察を得ることを望んでいます。

乾杯。

回答 1 件
  • .onWrite((change, context) => {
        if ( !change.before.exists() || !change.after.exists()) {
            return null;
        }
        const beforeScore = parseFloat(change.before.val()['score']);
        const afterScore = parseFloat(change.after.val()['score']);
        const crowdStatsRef = change.after.ref.parent.parent.child('crowdStats');
        return Promise.all( [
            crowdStatsRef.child('userCount').once('value'),
            crowdStatsRef.child('averageScore').once('value')
        ]).then((snapshots) => {
            return crowdStatsRef.transaction((crowdStatsNode) => {
                if (crowdStatsNode) {
                    const userCount = snapshots[0].val();
                    const averageScore = snapshots[1].val();
                    const currentAverage = (( ( averageScore * userCount ) - beforeScore + afterScore ) / userCount ).toFixed(2);
                    crowdStatsNode.score = parseFloat(currentAverage);
                }
                return crowdStatsNode;
            }, (error, committed, snapshot) => {
                if (error) {
                    console.error(error);
                }
            });
        });
    });
    
    

    トランザクションの仕組みを誤解しました。ロックしているオブジェクトは、コールバック関数で返される必要があります。また、ここでそのコールバック関数のnullチェックが不可欠です。

    以下に例を示します。 https://firebase.googleblog.com/2016/01/keeping-our-promises-and-callbacks_76.html

あなたの答え