Асинхронная функция не возвращает ожидаемые данные в Flutter

Я пытаюсь подтвердить номер телефона с помощью firebase. Но получить неожиданный результат от асинхронной функции. Вот мой код:

  bool isVerificationSuccess = false;

  Future<bool> verifyUserPhoneNumber(String phoneNumber) async {
    await FirebaseAuth.instance.verifyPhoneNumber(
      phoneNumber: phoneNumber,
      timeout: Duration(seconds: 60),
      verificationCompleted: (credential) => verificationComplete(credential),
      verificationFailed: (authException) => verificationFailed(authException),
      codeAutoRetrievalTimeout: (verificationId) =>
          codeAutoRetrievalTimeout(verificationId),
      codeSent: (verificationId, [code]) => smsCodeSent(verificationId, [code]),
    );
    print("Status from service : $isVerificationSuccess");
    return isVerificationSuccess;
  }

  verificationComplete(AuthCredential credential) async {
    FirebaseUser user = await FirebaseAuth.instance.currentUser();

    user.linkWithCredential(credential).then((_) {
      print("User Successfully Linked");
      isVerificationSuccess = true;
    }).catchError((e) {
      print("Linking Error : ${e.toString()}");
    });
  }

Вот вывод:

 Status from service : false
 User Successfully Linked

Так что здесь функция verifyUserPhoneNumber возвращает еще до завершения FirebaseAuth.instance.verifyPhoneNumber() , поэтому она не возвращает ожидаемые данные (всегда false ), даже если проверка прошла успешно. Что здесь не так?

Всего 1 ответ


Проблема в том, что вызов функции в этой строке:

verificationCompleted: (credential) => verificationComplete(credential),

не ожидается, хотя сама функция является асинхронной. Итак, что происходит:

  1. verifyUserPhoneNumber вызывается откуда-то
  2. FirebaseAuth.instance.verifyPhoneNumber ожидается
  3. В рамках этого вызова вызывается verificationComplete(credential) и, поскольку он сам содержит оператор await, он будет поставлен в очередь в цикле событий Dart. Так что бы ни случилось после FirebaseUser user = await FirebaseAuth.instance.currentUser(); задерживается!
  4. verifyUserPhoneNumber теперь продолжает выполняться и возвращает false .
  5. После того, как значение уже было возвращено, теперь verificationComplete черед verificationComplete validComplete. Это изменит логическое значение, а затем выйдет.

Здесь я рекомендую не использовать глобальную переменную, а вместо этого, например, вызывать verificationComplete после того, как FirebaseAuth.instance.verifyPhoneNumber уже полностью завершил обработку и вернул ее.

Изменить: Вот как вы могли бы теоретически решить проблему, хотя это не особенно красиво, я признаю:

  Future<bool> verifyUserPhoneNumber(String phoneNumber) async {
    final completer = Completer<AuthCredential>();
    await FirebaseAuth.instance.verifyPhoneNumber(
      phoneNumber: phoneNumber,
      timeout: Duration(seconds: 60),
      verificationCompleted: completer.complete,
      verificationFailed: completer.completeError,
      codeAutoRetrievalTimeout: (verificationId) =>
          codeAutoRetrievalTimeout(verificationId),
      codeSent: (verificationId, [code]) => smsCodeSent(verificationId, [code]),
    );
    try {
      final credential = await completer.future;
      return await verificationComplete(credential);
    } catch (e) {
      verificationFailed(e);
      return false;
    }
  }

  Future<bool> verificationComplete(AuthCredential credential) async {
    FirebaseUser user = await FirebaseAuth.instance.currentUser();
    try {
      await user.linkWithCredential(credential);
      print("User Successfully Linked");
      return true;
    } catch (e) {
      print("Linking Error : ${e.toString()}");
      return false;
    }
  }

Есть идеи?

10000