Подтвердить что ты не робот

Текущие текущие данные транзакции транзакции Firebase равны нулю

Когда я использую transaction() для обновления местоположения, данные в этом месте возвращают null, хотя местоположение имеет некоторые данные.

Я пробовал transaction() после чтения данных в том же месте, что и время, когда он передает все данные в этом месте.

Как я могу использовать transaction(), если это так, как указано выше?

4b9b3361

Ответ 1

Транзакции работают в манере Amazon SimpleDB или кластерных баз данных. То есть, они "в конечном итоге согласуются", а не гарантируются согласованными.

Поэтому, когда вы используете транзакции, функция обработки может вызываться более одного раза с локальным значением (в некоторых случаях null, если она никогда не была восстановлена), а затем снова с синхронизированным значением (независимо от того, что на сервере).

Пример:

pathRef.transaction(function(curValue) {

    // this part is eventually consistent and may be called several times

}, function(error, committed, ss) {

    // this part is guaranteed consistent and will match the final value set

});

Это действительно образ мышления, с которым вы все равно должны подходить к транзакции. Вы всегда должны ожидать несколько вызовов, поскольку первая транзакция может столкнуться с другим изменением и быть отклонена. Вы не можете использовать метод обработки транзакции для получения значения сервера (хотя вы можете прочитать его из обратного вызова успеха).

Предотвращение локально вызванного события

Когда транзакция происходит, локальное событие запускается до того, как оно достигнет сервера для компенсации задержки. Если транзакция завершится с ошибкой, локальное событие будет отменено (срабатывает событие изменения или удаления).

Вы можете использовать свойство applyLocally для транзакций, чтобы переопределить это поведение, что делает локальные результаты медленнее, но гарантирует, что только сервер значение запускается локально.

pathRef.transaction(function(curValue) {

    // this is still called multiple times

}, function(error, committed, ss) {

    // this part is guaranteed consistent and will match the final value set

}, 
    // by providing a third argument of `true`, no local event
    // is generated with the locally cached value.
true);

Ответ 2

Вам нужно следовать этому шаблону:

var pinRef = firebase.database().ref('vm-pin-generator');
pinRef.transaction(function(oldPin) {
    // Check if the result is NOT NULL:
    if (oldPin != null) {
        return localPinIncrementor(oldPin);
    } else {
        // Return a value that is totally different 
        // from what is saved on the server at this address:
        return 0;
    }
}, function(error, committed, snapshot) {
    if (error) {
        console.log("error in transaction");
    } else if (!committed) {
        console.log("transaction not committed");
    } else {
        console.log("Transaction Committed");
    }
}, true);

Firebase обычно возвращает нулевое значение при первом извлечении ключа, но при сохранении его проверяет, похоже ли новое значение на более раннее значение или нет. Если нет, firebase снова запустит весь процесс, и на этот раз сервер вернет правильное значение.

Добавление проверки null и возврат совершенно неожиданного значения (0 в этом случае) заставит firebase снова запустить цикл.