Проблема с фьючерсами на дротики во флаттере: ошибочное утверждение: строка 146: «<оптимизировано>»: не соответствует действительности - PullRequest
0 голосов
/ 08 ноября 2018

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

Во-первых, здесь выдается ошибка:

E / flutter (17162): [ОШИБКА: флаттер / shell / common / shell.cc (188)] Ошибка дротика: необработанное исключение: E / flutter (17162): 'dart: async / future_impl.dart': ошибочное утверждение: строка 146: 'optimized out': неверно. E / flutter (17162): # 0 _AssertionError._doThrowNew (dart: core / runtime / liberrors_patch.dart: 40: 39) E / flutter (17162): # 1 _AssertionError._throwNew (dart: core / runtime / liberrors_patch.dart: 36: 5) E / flutter (17162): # 2 _FutureListener.handleError (dart: async / future_impl.dart: 146: 14) E / flutter (17162): # 3 Future._propagateToListeners.handleError (dart: async / future_impl.dart: 654: 47) E / flutter (17162): # 4 Future._propagateToListeners (dart: async / future_impl.dart: 675: 24) E / flutter (17162): # 5 Future._completeError (dart: async / future_impl.dart: 494: 5) E / flutter (17162): # 6 _SyncCompleter._completeError (dart: async / future_impl.dart: 55: 12) E / flutter (17162): # 7 _Completer.completeError (dart: async / future_impl.dart: 27: 5) E / flutter (17162): # 8 _AsyncAwaitCompleter.completeError (dart: async / runtime / libasync_patch.dart: 40: 18) E / flutter (17162): # 9 FirebaseAuth.signInWithEmailAndPassword (пакет: firebase_auth / firebase_auth.dart) E / флаттер (17162): E / flutter (17162): # 10 Session.login. (Упаковка: mood_map / утилиты / session.dart: 31: 24) E / flutter (17162): # 11 _RootZone.runUnary (dart: async / zone.dart: 1379: 54) E / flutter (17162): # 12 _FutureListener.handleValue (дротик: async / future_impl.dart: 129: 18) E / flutter (17162): # 13 Future._propagateToListeners.handleValueCallback (дарт: async / future_impl.dart: 642: 45) E / flutter (17162): # 14 Future._propagateToListeners (dart: async / future_impl.dart: 671: 32) E / flutter (17162): # 15 Future._complete (дротик: async / future_impl.dart: 476: 7) E / flutter (17162): # 16 _SyncCompleter.complete (дарт: async / future_impl.dart: 51: 12) E / flutter (17162): # 17 _AsyncAwaitCompleter.complete (dart: async / runtime / libasync_patch.dart: 28: 18) E / flutter (17162): # 18 _completeOnAsyncReturn (dart: async / runtime / libasync_patch.dart: 295: 13) E / flutter (17162): # 19 Session._checkUserAlreadyExists (пакет: mood_map / utilities / session.dart) E / флаттер (17162): E / flutter (17162): # 20 Session.login (пакет: mood_map / utilities / session.dart: 27: 11)

А вот функции, которые задействованы:

static final FirebaseAuth _authenticator = FirebaseAuth.instance;

static void login(BuildContext context, String email, String password) async {

email = email.trim();
password = password.trim();

//Check if the user already exists
await _checkUserAlreadyExists(email).then((exists) {

  if(exists) {

    _authenticator.signInWithEmailAndPassword(email: email, password: password)
        .then((FirebaseUser user) { _loginSuccess(); })
        .catchError((Error e) { _loginFailure(context); });

  } else {

    Utilities.showMessageDialog(context, "That user doesn't exist. Please create an account below.");

  }

});

} 

----------------------------------------------------------------------

static Future createUserAccount(BuildContext context, email, String password) async {

//Check if the user already exists
await _checkUserAlreadyExists(email).then((exists) {

  if(exists) {

    Utilities.showMessageDialog(context, "That user already exists. Please login or select another account.");
    AppNavigator.navigateToLoginScreen();

  } else {

    _authenticator.createUserWithEmailAndPassword(email: email, password: password)
        .then((FirebaseUser user) { _createUserSuccess(); })
        .catchError((Error e) { _createUserFailure(context); });

  }

});

}

Короче говоря, вызов _authenticator.signonWithEmailAndPassword () не выполняется. Я знаю, что экземпляр _authenticator работает с другими функциями, поэтому я знаю, что это не проблема самого Firebase.

Меня беспокоит, что я что-то делаю неправильно, вызывая другую асинхронную функцию _authenticator.signonWithEmailAndPassword () из другой асинхронной функции _checkIfUserAlreadyExists (). Кажется, что это должно быть нормально делать изнутри блока .then () из того, что я прочитал, но сообщение об ошибке кажется довольно настойчивым, что это как-то связано с настройкой асинхронного характера вызовов функций.

Мысли

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Попробуйте использовать async - await , чтобы перехватить ошибки в «последнем шаге». Этот ответ https://github.com/flutter/flutter/issues/22734 мне очень помог.

Ниже приведен фрагмент кода, полученный из источника, который я не помню, но он помог мне понять, как правильно работать с Future s. Я немного изменил его, чтобы проверить мою точную ситуацию (добавлены функции main4 () и divFullAsyncNested () ). Надеюсь, это поможет.

// SO 29378453
import 'dart:async';

import 'package:login_app/constants.dart';

main() {
  // fails
  main1();
  main2();
  main3();
  main4();
}

Future<double> divide(int a, b) {
  // this part is still sync
  if (b == 0) {
    throw new Exception('Division by zero divide non-async');
  }
  // here starts the async part
  return new Future.value(a / b);
}

Future<double> divideFullAsync(int a, b) {
  return new Future(() {
    if (b == 0) {
      throw new Exception('Division by zero full async');
    }
    return new Future.value(a / b);
    // or just
    // return a / b;
  });
}

Future<double> divideFullAsyncNested() {
  return divideFullAsync(7, 8).then(
    (val) {
      return divideFullAsync(5, 0).then(
        (val2) {
          return Future(() {
            if (val2 == 1) {
              throw Exception('Innermost: Result not accepted exception.');
            }
            return val2;
          });
        },
      ).catchError((err) => throw Exception('Inner:    $err'));
    },
  ).catchError((err) => throw Exception('Outter: $err'));
}

//Future<double> divideFullAsyncNested() {
//  return divideFullAsync(9, 9).then(
//    (val) {
//      return Future(
//        () {
//          if (val == 1) {
//            throw Exception('Result not accepted exception.');
//          }
//          return val;
//        },
//      );
//    },
//  ).catchError((err) => throw Exception(err.toString()));
//}

// async error handling doesn't catch sync exceptions

void main1() async {
  try {
//    divide(1, 0).then((result) => print('(1) 1 / 0 = $result')).catchError(
//        (error) => print('(1)Error occured during division: $error'));
    var result = await divide(1, 0);
    print('(1) 1 / 0 = $result');
  } catch (ex) {
    print('(1.1)Error occured during division: ${ex.toString()}');
  }
}

// async error handling catches async exceptions
void main2() {
  divideFullAsync(1, 0)
      .then((result) => print('(2) 1 / 0 = $result'))
      .catchError(
          (error) => print('(2) Error occured during division: $error'));
}

// async/await allows to use try/catch for async exceptions
main3() async {
  try {
    await divideFullAsync(1, 0);
    print('3');
  } catch (error) {
    print('(3) Error occured during division: $error');
  }
}

main4() async {
//  try {
//    await divideFullAsyncNested();
//  } on Exception catch (e) {
//    print("(4) ${e.toString().replaceAll('Exception:', '').trimLeft().trimRight()}");
//  }
  try {
    divideFullAsyncNested()
        .then((v) => print(v))
        .catchError((err) => print(Constants.refinedExceptionMessage(err)));
  } on Exception catch (e) {
    print("(4) ${Constants.refinedExceptionMessage(e)}");
  }
}
0 голосов
/ 08 ноября 2018

Если вы используете .then(), предложения не используют await.

.then() и await - два разных способа обработки Future, но их нельзя использовать для одного и того же экземпляра Future.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...