【问题标题】:firebase transcational decrease valuefirebase 交易减少值
【发布时间】:2019-02-01 19:30:56
【问题描述】:

我有以下问题:

交易更新功能问题:

尝试减少存储在实时数据库路径中的当前值。 我尝试以与我在许多关于increase的答案中看到的类似方式处理当前值为空时调用的第一次事务。 例如增加阅读次数等。

在所有示例中都以类似的方式显示:

    return (current || 0) + 1;

但在我的情况下,只有当当前值大于参数时,我才需要减小某个值。 多个用户可能会尝试减少相同的值,因此我需要在事务中执行此操作。 这是我的代码:

    seatsCountRef.transaction((current)=>{
        if ((current || 0) >= 1) {
            return (current || 0) - 1;
        } 
    })

但减少永远不会成功。所以这是我在第 1 点中的主要问题。

我在第 1 点中的另一个问题是:根据文档,如果我不返回任何内容,则交易被中止。

我也试试这个方法:

    ...
    else {
        return; // abort the transaction
    }

但在这两种情况下,我都收到了部署警告。有什么提示吗?

==== 我已经切断了另一部分,因为正如 Frank van Puffelen 所说,这是一个单独的问题 ===

所以现在这是一个没有外部依赖的简单问题。

我只是想知道减少交易的正确方法是什么。

因为所有的例子和教程都是关于增加的,更新功能很简单

    return (current || 0) + 1;

但是当我尝试这样做时

    if ((current || 0) >= 1) {
        return (current || 0) - 1;
    } 

交易永远不会成功。

【问题讨论】:

  • 您在这篇文章中有两个不同的问题。请将每个帖子限制为一个问题,并在每个帖子中尽最大努力create a minimal complete verifiable reproduction。例如,第二个 sn-p 看起来非常复杂,我们仍然看不到 data 是什么以及它来自哪里。尝试创建一段没有外部依赖关系的代码,并包含它操作的 JSON(作为文本,请不要截图)。
  • 对不起,我的错。我已经编辑了帖子,以便不包含数据和外部依赖项。我已经在它试图操纵的 db 中添加了 json。
  • 您希望return new Error('Failure', error); 做什么?此时事务已经完成,因此您无法再以原子方式更改数据库。
  • 好的,我已经切断了第二个问题。我需要关于基本的建议 - 减少交易。我已经更新了帖子。

标签: javascript firebase firebase-realtime-database transactions


【解决方案1】:

此代码不起作用:

seatsCountRef.transaction((current)=>{
    if ((current || 0) >= 1) {
        return (current || 0) - 1;
    } 
})

记住我在你的first question on this piece of code 中展示的内容:

...直到您的写入成功且没有冲突或您通过不从更新函数返回值来中止事务

现在查看您的代码,知道它第一次运行 Firebase 时可能会传入 null 作为当前值:

if ((current || 0) >= 1) {
    return (current || 0) - 1;
} 

如果currentnull,则变为:

if ((null || 0) >= 1) {
    return (null || 0) - 1;
} 

变成:

if (0 >= 1) {
    return 0 - 1;
} 

由于0 >= 1 如果false,您没有返回值,因此中止事务。

您需要处理这个初始的null。即使您的用例表明该值不可能不存在,您的代码仍需要处理它,因为 Firebase SDK 可能会将null 作为其操作的一部分传递给您。

由于 null 不能真正存在于您的数据库中,因此在这种情况下返回 什么 并不重要。重要的是您返回 something 以确保事务不会中止。例如,这会起作用:

seatsCountRef.transaction((current)=>{
    if ((current || 0) >= 1) {
        return (current || 0) - 1;
    } 
    return "This will never be stored";
})

但是由于这个值永远不会被存储,你不妨简单地返回最简单的代码导致的-1

seatsCountRef.transaction((current)=>{
    return (current || 0) - 1;
})

如果您担心这个无效值会被存储,您可以在 security rules 中捕获并拒绝它:

"seatsCount": {
  ".validate": "newData.isNumber() && newData.val() >== 0"
}

总的来说,这实际上是一个非常好的做法:一旦您的数据模型稳定下来,就可以使用验证规则来强制执行它。不过在这里不会有什么不同,因为您已经说过seatsCount 必须存在。但以防万一,此安全规则将捕获交易的输出。

【讨论】:

    【解决方案2】:

    感谢您的建议,Frank van Puffelen,

    经过更多的实验,我有一个适合我的代码:

    (并处理空情况)

    return seatsCountRef.transaction((current)=>{
        if (current) {
            if (current >= 1) {
                return current - 1;
            }
        }
        return current;
    })
    

    【讨论】:

      猜你喜欢
      • 2016-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多