如何正确处理FirebaseAuth异步结果?

时间:2020-02-13 19:38:13

标签: android async-await firebase-authentication kotlin-coroutines

在我的Android应用上,我正在尝试使用FirebaseAuth实现一个简单的登录/注册。我想使用Kotlin协程来正确处理Firebase的响应。 因此,我将其添加到了我的gradle文件中:

"org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$kotlin_play_services_version"

之后,我能够在FirebaseAuth请求之后调用.await()。 因此,这是负责处理登录的代码:

override suspend fun signIn(email: String, password: String): JobResult<User> {

    var errorMessage = ""
    var user: User? = null

    firebaseAuth.signInWithEmailAndPassword(email, password)
        .addOnSuccessListener { result ->
            user = UserMapper().mapFromFirebaseUser(result.user)
        }
        .addOnFailureListener { result ->
            errorMessage = result.message ?: CONSTANTS.BAD_REQUEST
            user = null
        }.await()

    user?.run {
        return JobResult.Success(this)
    }
    return JobResult.Fail(errorMessage, HttpURLConnection.HTTP_BAD_REQUEST)

}

所以基本上发生的是,我正在调用Firebase的Sign In方法传递正确的参数,并添加成功和失败侦听器。根据结果​​,变量user可能包含用户的信息或为null。然后根据该变量,将成功或失败的结果返回给请求它的代码部分。

如果结果为肯定(成功侦听器),则一切正常,但是,如果结果不是成功的结果,则.await()调用之后的代码将永远不会执行!好像它正在等待成功的结果,并将永远等待它。这意味着,如果请求由于某种原因而失败,则暂停功能将永远不会返回任何结果,而只是等待。

我希望其余的代码在收到任何结果后立即运行。我该怎么做?我在这里错过明显的东西吗? 到达故障监听器后,是否有任何方法可以“突破”该await()并继续执行其余代码?

谢谢!

2 个答案:

答案 0 :(得分:1)

您应该这样写。如果您要使用协程,则无需在Task上附加回调侦听器。只需await()任务,然后使用try / catch处理结果:

try {
    val result = firebaseAuth.signInWithEmailAndPassword(email, password).await()
    val user = UserMapper().mapFromFirebaseUser(result.user)
    // continue using user here...
}
catch (e: Exception) {
    // deal with the error properly
}

答案 1 :(得分:-1)

override suspend fun signIn(email: String, password: String): JobResult<User> = suspendCancellableCoroutine  { cont -> 

var errorMessage = ""
var user: User? = null

firebaseAuth.signInWithEmailAndPassword(email, password)
    .addOnSuccessListener { result ->
        user = UserMapper().mapFromFirebaseUser(result.user)
        if(cont.isActive){
           cont.resume(JobResult.Success(this))
        }
    }
    .addOnFailureListener { result ->
        errorMessage = result.message ?: CONSTANTS.BAD_REQUEST
        user = null
        if(cont.isActive){
            cont.resume(JobResult.Fail(errorMessage, HttpURLConnection.HTTP_BAD_REQUEST))
        }
    }
}