我遇到以下问题:
交易更新功能问题:
尝试减小存储在实时数据库路径中的当前值。 我尝试处理当当前值为null时第一次调用事务的情况,这与我在关于 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;
}
交易永远不会成功。
答案 0 :(得分:2)
此代码无效:
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;
}
如果current
是null
,则变成:
if ((null || 0) >= 1) {
return (null || 0) - 1;
}
哪个会变成:
if (0 >= 1) {
return 0 - 1;
}
由于0 >= 1
是false
,因此您没有返回值,因此中止了事务。
您需要处理此初始null
。即使您的用例表明不可能甚至不存在该值,您的代码也仍将需要处理它,因为Firebase SDK可能会将null
作为其操作的一部分传递给您。
由于null
不能真正存在于数据库中,因此在这种情况下返回的内容并不重要。重要的是您返回某物以确保交易不会中止。例如,这将起作用:
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
必须存在。但是,以防万一,该安全规则将捕获事务的输出。
答案 1 :(得分:0)
谢谢您的建议,弗兰克·范·普菲伦,
经过更多的实验,我有一个适合我的代码:
(并处理空值情况)
Sub Order()
Dim I As Double
Dim strKeyWord As String
Dim myCount As Integer
Dim checkEmpty As Range
Dim N As Long
Dim SubTotal As Range, Country As Range, DisCount As Range, RequiredData As Range
Dim wsOrder As Worksheet
Dim wsCondition As Worksheet
Dim wbOrder As Workbook
Dim wbCondition As Workbook
Dim OrderFile As String
Dim ConditionFile As String
'Open Order wb
OrderFile = Application.GetOpenFilename()
Set wbOrder = Workbooks.Open(OrderFile)
Set wsOrder = wbOrder.Worksheets(1)
'Open Condition wb
ConditionFile = Application.GetOpenFilename()
Set wbCondition = Workbooks.Open(ConditionFile)
Set wsCondition = wbCondition.Worksheets(1)
With wsCondition
.Range("B1").Value = "Product code"
.Range("C1").Value = "Order Condition"
.Range("D1").Value = "Subtotal"
.Range("E1").Value = "Discount"
.Range("F1").Value = "Country"
End With
'using the CountA ws function (all non-blanks)
myCount = Application.CountA(wsCondition.Range("A:A"))
For I = 2 To myCount Step 1
strKeyWord = wsCondition.Range("A" & I)
wsOrder.Range("R:R").AutoFilter Field:=1, Criteria1:="=*" & strKeyWord & "*"
'lRow1 = WorksheetFunction.Max(wsOrder.Range("I65536").End(xlUp).Row)
If wsOrder.Cells(Rows.Count, 1).End(xlUp).Row > 1 Then
Set SubTotal = wsOrder.Range("I2", wsOrder.Range("I" & Rows.Count).End(xlUp))
Set Country = wsOrder.Range("AG2", wsOrder.Range("AG" & Rows.Count).End(xlUp))
Set DisCount = wsOrder.Range("N2", wsOrder.Range("N" & Rows.Count).End(xlUp))
Set RequiredData = Union(SubTotal, Country, DisCount)
RequiredData.SpecialCells(xlCellTypeVisible).Copy
With wsCondition
.Cells(.Rows.Count, "B").End(xlUp).Offset(1).Value = strKeyWord
.Cells(.Rows.Count, "C").End(xlUp).Offset(1).Value = "Availabe"
.Cells(.Rows.Count, "D").End(xlUp).Offset(1).PasteSpecial
End With
Else
With wsCondition
.Cells(.Rows.Count, "B").End(xlUp).Offset(1).Value = strKeyWord
.Cells(.Rows.Count, "C").End(xlUp).Offset(1).Value = "no Order"
.Cells(.Rows.Count, "D").End(xlUp).Offset(1).Value = "N/A"
.Cells(.Rows.Count, "E").End(xlUp).Offset(1).Value = "N/A"
.Cells(.Rows.Count, "F").End(xlUp).Offset(1).Value = "N/A"
End With
End If
Next I
End Sub