Firebase事务和if-then-else行为

时间:2018-08-26 06:39:04

标签: javascript firebase firebase-realtime-database transactions

我的要求有一些变化:

不仅创建/请求/取消整个要约,还对要约的详细信息执行一些操作:

这是activeOffers列表中的一个报价:

activeOffers
    -LKohyZ58cnzn0vCnt9p
        details
            direction: "city"
            seatsCount: 2
            timeToGo: 5
        uid: "-ABSIFJ0vCnt9p8387a"    ---- offering user

用户应该能够“要求座位”,并且如果成功,则优惠记录应如下所示:

activeOffers
    -LKohyZ58cnzn0vCnt9p
        details
            direction: "city"
            seatsCount: 1   ----- reduced count
            timeToGo: 5
        uid: "-ABSIFJ0vCnt9p8387a"
    deals
        -GHFFJ0vCnt9p8345b   -----   the userId of asking user
            seatsCount: 1
            status: "asked"

但是执行如下所示的源代码后,我遇到了3个问题:

(如上图所示,优惠有2个席位,用户要求1个席位)

  1. 在我的日志中执行后,我同时拥有“减少席位数减1”和“席位不足” ...即:“ if-then-else”的“ then”和“ else”部分: o

  2. 函数结果为[]-即未创建交易。

  3. 我不确定该如何执行TODO:部分-使用询问userId作为KEY在DealsRef下添加子项(新的交易对象),因为我认为这里不需要自动生成的密钥。

  4. p>

输入数据具有以下结构:

data
    "uid": "-GHFFJ0vCnt9p8345b",    ----- the userId of asking user
    "id": "-LKohyZ58cnzn0vCnt9p",    ----- the id of offer
    "details":
        "seatsCount": 1

这是我的代码:

dealSeats = function(data) {

const TAG = '[dealSeats]: ';

var details = data.details;
var info = data.info;

var entryRef = db.ref('activeOffers/' + data.id);
var entryDetailsRef = entryRef.child('details');
var seatsCountRef = entryDetailsRef.child('seatsCount');

var success = false;
return seatsCountRef.transaction((current)=>{
    var value = current;
    if (value >= details.seatsCount) {
        success = true;
        value = value - details.seatsCount;
        console.log(TAG + 'Reducing seats count by ' + details.seatsCount);
    } else {
        console.log(TAG + 'Not enought seats');
    }
    return value;
})
.then(()=>{
    var deal = [];
    if (success) {
        console.log(TAG + 'Succes');
        deal.seatsCount = details.seatsCount;
        deal.status = 'asked';
    // TODO: here should add the new deal to dealsRef
        return deal;
    } else {
        console.log(TAG + 'Failure');
        return deal;
    }
})
}

正如您所看到的-我不确定检查交易是否成功的正确方法是什么...

1 个答案:

答案 0 :(得分:1)

reference documentation for DatabaseReference.transaction says

  

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

所以中止事务的方法是不从更新函数返回任何值。这意味着整个第一块可以简化为:

seatsCountRef.transaction((current)=>{
    if (current >= details.seatsCount) {
        return value - details.seatsCount;
    }
})

现在,它要么返回新值,要么不返回任何值。后者将使Firebase中止交易。

要检测事务的最终输出,我发现使用完成回调(而不是Promise)最简单,因为它在一次调用中为您提供了所有参数:

seatsCountRef.transaction((current)=>{
    if (current >= details.seatsCount) {
        return value - details.seatsCount;
    }
}, function(error, committed, snapshot) {
  if (error) {
    console.log('Transaction failed abnormally!', error);
  } else if (!committed) {
    console.log('We aborted the transaction, because there are not enough seats.');
  } else {
    console.log('Seat count updated');
  }
})

第一个错误情况的最常见原因是必须过于频繁地重试该交易,这意味着太多用户试图同时要求获得席位。一种典型的解决方案是放弃,即让客户端稍后重试。