如果不同的条件成立,Firebase如何中断具有不同状态/消息的实时数据库事务?

2024-03-14

这是一个好的做法吗如果是的话什么是正确的方法针对不同情况使用不同的错误状态/消息来中断事务?

我有一个事务在“优惠”条目上运行,进行“座位”预订:

如果满足以下 3 个条件之一,我想打破它并将状态/消息返回给调用者函数.

  1. 如果提出请求的用户已经预订了该优惠的座位。
  2. 如果座位不够。
  3. 如果此优惠不存在。

如果一切正常,事务应该正常完成,并向调用者函数返回已进行预订的状态/消息。

我不确定在其中一个条件成立的情况下如何中断交易。

  • 如果我使用throw new Error('问题的描述。')那么这将是一个例外并且它不是由交易 Promise 的 catch() 处理程序处理的 我不知道如何处理这个异常,因为它是一个异步函数。 所以我认为我不应该使用异常。

我的意思是:

dealSeats = function(entryRef, data) {
    const TAG = '[dealSeats]: ';
    return entryRef.transaction((entry)=>{
        if (entry) {
            if ((entry.deals) && (entry.deals[data.uid])) {
                **? how to break the transaction with state/message 'You already have a deal.' ? and how to handle it below ?**
            } else if (entry.details.seatsCount >= data.details.seatsCount) {
                entry.details.seatsCount -= data.details.seatsCount;
                var deal = [];
                deal.status = 'asked';
                deal.details = data.details;
                if (!entry.deals) {
                    entry.deals = {};
                }
                entry.deals[data.uid] = deal;
            } else {
                **? how to break the transaction with state/message 'Not enought seats.' ? and how to handle it below ?**
            }
        }
        return entry;
        **? how to check if 'entry' is really null ? i.e. offer does not exists ?** and break and handle it.
    })
    .then((success)=>{
        return success.snapshot.val();
    })
    .catch((error)=>{
        return Promise.reject(error);
    });
}

这是我在实时数据库中的数据:

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

这是我的Postman发送的测试数据:

{
 "data": 
  {
     "uid": "-FGKKSDFGK12387sddd",    ---- the requesting/asking user
     "id": "-LKpCACQlL25XTWJ0OV_",
     "details":
     {
         "direction": "city",
         "seatsCount": 1,
         "timeToGo": 5
     }
  }
}

====更新了最终来源====

非常感谢雷诺·塔尔内克!

所以这是我的最终来源,工作正常。如果有人发现潜在问题,请告诉我。谢谢。

dealSeats = function(entryRef, data) {
    const TAG = '[dealSeats]: ';
    var abortReason;

    return entryRef.transaction((entry)=>{
        if (entry) {
            if ((entry.deals) && (entry.deals[data.uid])) {
                abortReason = 'You already made a reservation';
                return; // abort transaction
            } else if (entry.details.seatsCount >= data.details.seatsCount) {
                entry.details.seatsCount -= data.details.seatsCount;
                var deal = [];
                deal.status = 'asked';
                deal.details = data.details;
                if (!entry.deals) {
                    entry.deals = {};
                }
                entry.deals[data.uid] = deal;
                // Reservation is made
            } else {
                abortReason = 'Not enought seats';
                return; // abort transaction
            }
        }
        return entry;
    })
    .then((result)=>{ // resolved
        if (!result.committed) { // aborted
            return abortReason;
        } else {
            let value = result.snapshot.val();
            if (value) {
                return value;
            } else {
                return 'Offer does not exists';
            }
        }
    })
    .catch((reason)=>{ // rejected
        return Promise.reject(reason);
    });
}

唯一的痛苦是在 VSCode 终端中部署期间会出现有关此中止的警告,因为不返回任何值:

warning  Arrow function expected no return value  consistent-return

目前我不确定我是否能对此做些什么。


查看 Firebase API 参考文档中的此文档:https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction

以下是该文档中的代码。看看怎么样return;用于中止事务(文档还说:“您通过不从更新函数返回值来中止事务”)。并注意这个特定情况是如何处理的onComplete()事务完成时调用的回调函数(在else if (!committed){} ).

// Try to create a user for ada, but only if the user id 'ada' isn't
// already taken
var adaRef = firebase.database().ref('users/ada');
adaRef.transaction(function(currentData) {
  if (currentData === null) {
    return { name: { first: 'Ada', last: 'Lovelace' } };
  } else {
    console.log('User ada already exists.');
    return; // Abort the transaction.
  }
}, function(error, committed, snapshot) {
  if (error) {
    console.log('Transaction failed abnormally!', error);
  } else if (!committed) {
    console.log('We aborted the transaction (because ada already exists).');
  } else {
    console.log('User ada added!');
  }
  console.log("Ada's data: ", snapshot.val());
});

因此,恕我直言,您应该采用相同的模式,并在代码中询问“**?如何中断事务”的地方return;.

Update:您可以使用变量来区分堕胎情况,如下所示。如果您通过 Firebase 控制台添加一个节点age值 > 20 至users.ada.name,第一个流产原因就会被“触发”。

var adaRef = firebase.database().ref('users/ada');
var transactionAbortionCause;  //new variable
adaRef.transaction(function(currentData) {
  if (currentData === null) {
    return { name: { first: 'Ada', last: 'Lovelace' } };
  } else if (currentData.name.age > 20) {
    transactionAbortionCause = 'User ada is older than 20'; //update the variable
    console.log('User ada is older than 20');
    return; // Abort the transaction.
  } else {
    transactionAbortionCause = 'User ada already exists'; //update the variable
    console.log('User ada already exists');
    return; // Abort the transaction.
  }
}, function(error, committed, snapshot) {
  if (error) {
    console.log('Transaction failed abnormally!', error);
  } else if (!committed) {
    console.log('We aborted the transaction because ' + transactionAbortionCause);  //use the variable
  } else {
    console.log('User ada added!');
  }
  console.log("Ada's data: ", snapshot.val());
});

如果我没有记错的话,您也可以使用 Promise 来做到这一点,就像您在代码中所做的那样。文档说交易返回非空firebase.Promise含有{committed: boolean, snapshot: nullable firebase.database.DataSnapshot}并解释说这个承诺“可以选择用来代替onComplete处理成功和失败的回调”。

So by:

  1. Doing return;对于您的两起堕胎案件,以及
  2. 读取值committed boolean

您应该能够通过执行以下操作来处理代码中的堕胎情况

.then((result)=>{
    if (result.commited) {... } else { /*abortion!*/}
}) 

不过我还没有测试过这种方法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果不同的条件成立,Firebase如何中断具有不同状态/消息的实时数据库事务? 的相关文章

随机推荐