Firebase транзакция и поведение if-then-else - PullRequest
0 голосов
/ 26 августа 2018

У меня есть некоторые изменения в моих требованиях:

Не только создать / запросить / отменить все предложение, но и выполнить некоторые действия с деталями предложения:

Вот предложение в списке активных предложений:

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 "и" Недостаточно места "... то есть: часть then и else части if-then-else: o

  2. результат функции равен [] -т. е. сделка не создана.

  3. Я не уверен, как сделать TODO: часть - добавить дочерний элемент (новый объект сделки) в dealRef, используя запрос userId в качестве KEY, потому что я думаю, что яздесь не нужен автоматически сгенерированный ключ.

входные данные имеют следующую структуру:

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

AnВот мой код:

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 голосов
/ 26 августа 2018

Справочная документация для DatabaseReference.transaction говорит :

... до тех пор, пока ваша запись не будет выполнена успешно без конфликта или вы прервите транзакцию, не возвращая значение изваша функция обновления .

Таким образом, вы можете прервать транзакцию, не возвращая никакого значения из вашей функции обновления.Это означает, что весь первый блок может быть упрощен до:

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

Теперь он либо возвращает новое значение, либо ничего не возвращает.Затем последний заставит Firebase прервать транзакцию.

Чтобы определить окончательный результат транзакции, я считаю, что проще всего работать с обратным вызовом завершения (вместо Promise), поскольку он выдает все параметры в одномcall:

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');
  }
})

Наиболее распространенной причиной возникновения этой первой ошибки является то, что транзакцию пришлось повторять слишком часто, а это означает, что слишком много пользователей пытаются одновременно получить места.Типичным решением здесь является откат, то есть повторная попытка клиента.

...