【问题标题】:Firebase Cloud function triggers twice onUpdateFirebase Cloud 函数触发两次 onUpdate
【发布时间】:2018-01-08 03:30:50
【问题描述】:

我为firebase collection - payments 设置了以下规则

"payments": {
    "$paymentId": {
        "totalAmount": {
        },
        "balanceAmount": {
            ".validate": "newData.val()<=data.child('totalAmount').val()"
        },
        "paymentDetails": {
            "$detailId": {
                "amount": {
                    ".validate": "newData.isString()"
                },
            }
        },
    }
}

以及以下为处理该集合的某些更新而编写的云函数:

exports.calculateBalance = functions.database
.ref('payments/{pushId}')
.onUpdate(event => {
    const paymentRef = event.data.adminRef;
    const payment = event.data.val();
    return paymentRef.once('value').then(snapshot => {
        var paidAmount = 0;
        snapshot.child("paymentDetails").forEach(function(child) {
            paidAmount += parseFloat(child.child("amount").val());
        });
        return paidAmount;
    }).then(snap => {
        payment.balanceAmount = parseFloat(payment.totalAmount) - snap;
        return paymentRef.set(payment);
    })
});

很简单,每当我添加付款详细信息时,我都想更新balanceAmount。这里的问题是,每当该集合发生更新时,该函数都会触发两次。第一次从应用程序中显而易见,第二次因为paymentRef.set(payment); 行。

有什么方法可以避免第二次触发云功能吗?我不能在collection 级别上使用任何标志,因为付款详细信息的更新发生了多次。有人可以指导我正确的方向吗?

编辑

注意 - 我有一个输入付款详细信息的编辑选项。

【问题讨论】:

  • 您可以off 删除该节点上的侦听器,然后调用on 再次设置侦听器(我不是一个优秀的Web 开发人员,但我在android 上使用这种方法)
  • 您可以更新付款明细还是直接创建?

标签: android firebase firebase-realtime-database google-cloud-functions


【解决方案1】:

如果您只想在添加付款详情时更新余额金额,您可以直接在付款详情上使用 onCreate 触发器。

尝试类似的方法(您必须为您的案例更新代码):

exports.calculateBalance = functions.database.ref('payments/{pushId}/paymentDetails/{detailId}').onCreate(event => {
    var paymentRef = event.data.adminRef.parent.parent;
    var paymentDetailSnapshot = event.data;
    var paymentDetailAmountSnapshot = paymentDetailSnapshot.child('amount');

    return paymentRef.child('balanceAmount').transaction(current => {
        return current - paymentDetailAmountSnapshot.val(); // Balance can be negative
    });
});

(使用事务管理并发修改)

Transactions documentation.

注意

请直接为您的金额数据使用数字,而不是字符串

更新

添加此功能来管理更新:

exports.recalculateBalance = functions.database.ref('payments/{pushId}/paymentDetails/{detailId}').onUpdate(event => {
    var paymentRef = event.data.adminRef.parent.parent;

    var paymentDetailSnapshot = event.data;
    var previousPaymentDetailSnapshot = event.data.previous;

    var paymentDetailAmountSnapshot = paymentDetailSnapshot.child('amount');
    var previousPaymentDetailAmountSnapshot = previousPaymentDetailSnapshot.child('amount');

    return paymentRef.child('balanceAmount').transaction(current => {
        return current + previousPaymentDetailAmountSnapshot.val() - paymentDetailAmountSnapshot.val(); // Balance can be negative
    });
});

【讨论】:

  • 我很欣赏这一点,是的,非常适合,但是应用程序中也有一个编辑选项,所以我怀疑这不会有太大帮助.. :(
  • 给我一点时间..正在检查它.. :)
  • 你提到//余额可以是负数无论如何要克服这个?
  • 这只是一个例子,你可以返回你想要的
  • 好吧..我有点困惑..你能告诉我这是如何避免多次更新的吗?
猜你喜欢
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
  • 2017-08-25
  • 2020-04-28
  • 2018-07-29
  • 2020-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多