Как правильно связать фьючерсы с транзакцией с использованием firebase на флаттер?

Tree спросил: 12 мая 2018 в 05:01 в: firebase

Вот мой код. succes возвращает false, потому что длина документа равна 0.

   var sucess = await Firestore.instance.runTransaction((transaction) async {
      await transaction.set(userReference, userMap);
    }).then((_) {
      return Firestore.instance.collection(CollectionName.user).where(FirebaseUserField.uid, isEqualTo: userMap["uid"]).getDocuments();
    }).then((querySnapshot) {
      if (querySnapshot.documents.length == 0) {
        return false;
      }
      return true;
    }).catchError((e) {
      print(e);
      return false;
    });

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

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

runTransaction((Transaction) → Future<dynamic> transactionHandler, {Duration timeout: const Duration(seconds: 5)}) → Future<Map<String, dynamic>>

Каков надлежащий способ вызвать следующее будущее после завершения транзакции или войти в если это не сработает.

Следует учитывать, что когда я отлаживаю точку останова, где я запрашиваю пользователя, поэтому есть задержка, я получаю пользователя правильно.

Также пользователь правильно записывается в мою базу данных.

EDIT: я также пробовал

var sucess = await Firestore.instance.runTransaction((transaction) async {
      return transaction.set(userReference, userMap);
    })

, но это не сработало.

2 ответа

Edman ответил: 12 мая 2018 в 06:01

Я думаю, что это связано с вложенным await внутри вашей транзакции, что также объясняет состояние гонки, которое вы видите во время отладки.

Что происходит, когда вы используете эту транзакцию обработчик в runTransaction?

(transaction) {
  return transaction.set(userReference, userMap);
}
Tree ответил: 12 мая 2018 в 06:03
то же, уже пробовал это. Подумав, кажется, что состояние гонки связано с сервером Firebase, транзакция заканчивается на клиенте и сразу же запускает новый запрос на получение документа, но сервер Firebase также требует времени для обработки транзакции. Это только моя догадка.
Tree ответил: 12 мая 2018 в 06:05
Я просто прочитал документацию, когда транзакция завершена, это определенно, и данные записываются.
Edman ответил: 12 мая 2018 в 07:01
Вы пытались не сделать асинхронный обработчик транзакций и просто вернуть transaction.set? В вашем редактировании обработчик все еще асинхронный.
Tree ответил: 12 мая 2018 в 07:09
havent попытался, но, насколько я помню из документов, функция async не генерируется как микротранзакции
Tree ответил: 12 мая 2018 в 07:09
Я постараюсь это сделать
aqwert ответил: 12 мая 2018 в 06:49

Вы смешиваете фьючерсы с ожиданием. Попробуйте удалить первый запрос перед Firestore.instance.runTransaction

var sucess = Firestore.instance.runTransaction((transaction) async {
      await transaction.set(userReference, userMap);
    }).then((_) {
      return Firestore.instance.collection(CollectionName.user).where(FirebaseUserField.uid, isEqualTo: userMap["uid"]).getDocuments();
    }).then((querySnapshot) {
      if (querySnapshot.documents.length == 0) {
        return false;
      }
      return true;
    }).catchError((e) {
      print(e);
      return false;
    });

Возможно, вам также потребуется удалить await из await transaction.set(userReference, userMap); с тех пор который вернется немедленно с будущим, но не на 100% уверенным.