Je construis un module d'authentification d'utilisateur pour mon application et je rencontre des problèmes avec du code asynchrone.
Tout d'abord, voici l'erreur qui est lancée:
E/flutter (17162): [ERREUR: flutter/Shell/common/Shell.cc (188)] Erreur de fléchette: Exception non gérée: E/flutter (17162): 'Dart: async/future_impl.Dart': Échec de l'assertion: ligne 146: 'optimisé': n'est pas vrai . 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/exécution/libasync_patch.Dart: 40: 18) E/flutter (17162): # 9 FirebaseAuth.signInWithEmailAndPassword (package: firebase_auth/firebase_auth.Dart) E/flutter (17162): E/flutter (17162): # 10 Session.login. (package: mood_map/utilities/session.Dart: 31: 24) E/flutter (17162): # 11 _RootZone.runUnary (Dart: async/zone.Dart: 1379: 54) E/flutter (17162): # 12 _FutureListener.handleValue (Dart: async/future_impl.Dart: 129: 18) E/flutter (17162): # 13 Future._propagateToListeners.handleValueCallback (Dart: 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 (Dart: async/future_impl.Dart: 476: 7) E/flutter (17162): # 16 _SyncCompleter.complete (Dart: async/future_impl.Dart: 51: 12) E/flutter (17162): # 17 _AsyncAwaitCompleter.complete (Dart: async/exécution/libasync_patch.Dart: 28: 18) E/flutter (17162): # 18 _completeOnAsyncReturn (Dart: async/runtime/libasync_patch.Dart: 295: 13) E/flutter (17162): # 19 Session._checkUserAlreadyExists (package: mood_map/utilities/session.Dart) E/flutter (17162): E/flutter (17162): # 20 Session.login (package: mood_map/utilities/session.Dart: 27: 11)
Et voici les fonctions impliquées:
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); });
}
});
}
En bref, l'appel à _authenticator.signonWithEmailAndPassword () échoue. Je sais que l'instance _authenticator fonctionne avec d'autres fonctions, donc je sais que ce n'est pas un problème avec Firebase lui-même.
Je crains que je ne fasse quelque chose de mal en appelant une autre fonction asynchrone, _authenticator.signonWithEmailAndPassword () depuis une autre fonction asynchrone, _checkIfUserAlreadyExists (). Il semble que cela devrait être autorisé à partir d’un bloc .then () de ce que j’ai lu, mais le message d’erreur semble insister sur le fait qu’il est lié à la configuration de la nature asynchrone des appels de fonction.
Pensées?
Si vous utilisez les clauses .then()
, n'utilisez pas await
.
.then()
et await
sont deux manières différentes de traiter les Future
mais ne doivent pas être utilisés pour la même instance Future
.
Pensez à utiliser async - wait pour corriger les erreurs de la «dernière étape». Cette réponse https://github.com/flutter/flutter/issues/22734 m'a beaucoup aidé.
Vous trouverez ci-dessous un extrait de code provenant d'une source dont je ne me souviens plus, mais qui m'a aidé à comprendre comment travailler correctement avec Future s. Je l'ai modifié un peu pour tester ma situation exacte (ajout des fonctions main4 () et divideFullAsyncNested ()). J'espère que ça aide.
// 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)}");
}
}