我正在特定位置运行Firebase事务,但是在更新它之前,我需要确保它不大于特定数目。如何在Node.JS中执行此操作?我当前的代码无法正常工作。
我尝试的代码:
var reward_count_red_ref = admin
.database()
.ref("Rewards/" + Artcall_ID + "/" + reward_id + "/rewards_left");
reward_count_red_ref
.transaction(current => {
const increment = -1 * ticket_count;
console.log("Going to check if tickets are available");
if (ticket_count > current) {
console.log("Tickets not available. The current value is:", current);
} else {
return (current || 0) + increment;
console.log("They are available. The current value is: ", current);
}
})
.then(() => {
console.log("Tickets updated.");
admin
.database()
.ref(
"/Reserve_Project_Request/" + Artcall_ID + "/" + User_ID + "/Response"
)
.set("success");
});
最佳答案
您编写的代码缺少一些成分,可以帮助您调试问题并使其正常运行。
事务返回带有两个参数的对象:{ committed, snapshot }
。必须检查committed
布尔值,以查看事务是否确实更改了某些内容,这一点很重要。在您的情况下,如果committed
是false
,则要通知用户票证不可用。
另请注意,current
可能是null
(并且将在事务的大多数首次运行中使用)。您可能要以不同的方式处理这种情况,并检查snapshot.exists()
。
缺少的另一件事是catch
子句。您的交易很可能失败了。如果是这样,您可能会丢失它。这也是返回.set(...)
调用以确保您也捕获该结果的好计划。
可能出错的另一件事是,其他一些代码正在使用set
或update
修改该位置的数据。如果发生这种情况,交易将被取消。
至于事务本身中的代码,看起来还可以。 current || 0
没什么意义。如果current是null
并且ticket_count
是一个正数(我认为您应该在另一个地方为之保卫),它将永远不会到达此分支。
我会亲自将(current || 0) + increment
更改为current - ticket_count
以使其更具可读性,但这仅是味道。
更新资料
您可以这样访问committed
和snapshot
:ref.transaction(...).then(({ committed, snapshot }) => ...)
如果您想重试失败的事务,可以使用如下函数:
async function withRetries(ref, transaction, attempts = 0) {
try {
const result = await ref.transaction(transaction, undefined, false)
return result
} catch (e) {
if (attempts < MAX_TRANSACTION_ATTEMPTS) return withRetries(ref, transaction, attempts + 1)
throw new Error(`transaction failed ${MAX_TRANSACTION_ATTEMPTS} times, error: ${e.message}`)
}
}