如何在OnCompleteListener Firebase中使用异步/等待/协程 [英] How To Use Async/Await/Coroutines In OnCompleteListener Firebase

查看:126
本文介绍了如何在OnCompleteListener Firebase中使用异步/等待/协程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个客户端应用程序,该应用程序使用Firebase做两件事:

I am building a client application which uses Firebase for two things:

  • 用户身份验证
  • 使用实时数据库

我已经设法在客户端和后端服务器上正确设置了所有内容(使用Firebase的Admin SDK),并且能够正确验证用户身份并允许他们读取/写入数据库.

I have managed to set up everything correctly on my client and on my backend server (using Firebase's Admin SDK) and am able to correctly authenticate users and allow them to read/write to the database.

我还使用Retrofit2将请求从客户端发送到后端.

I am also using Retrofit2 to send requests from the client to the backend.

作为允许用户访问数据库的一部分,需要将用户的令牌发送到后端,以便可以验证用户.

As part of allowing users access to the database, it is needed to send the user's token to the backend so the user can be verified.

为此,我有以下逻辑:

val user = FirebaseAuth.getInstance().currentUser

    if (user != null) {
        user.getIdToken(false).addOnCompleteListener {
            if (it.isSuccessful) {
                val token = it.result?.token
                //retrofit logic to send request happens from here
            }
       }

如您所见,获取用户的ID令牌是一个异步调用,在我拥有的当前代码库中,对于后端(复制)的每个调用,我都有此代码块.

As you can see, getting the Id token of the user is an asynchronous call and in the current code base that I have, I have this code block for each one of my calls to the backend (duplication).

我想知道如何将该代码段导出到一个函数(也许是一个暂停方法?),以便可以在每次调用后端时重用它

我在网上进行搜索,看到了很多SO问题,但没有一个适合这种情况. 我曾考虑过传递一个回调,但是我有几种与后端通信的方法,每个方法都需要一个不同的回调方法.

I have searched online and have seen many SO questions, but none that fit this scenario. I have thought about passing in a callback, but I have several methods that communicate to the backend, and each of them will require a different callback method.

我正在寻找的解决方案看起来像这样:

The solution I am looking for looks something like this:

fun fetchDataFromDB() {
  getIdTokenForUser()
  //wait till it finishes and then
  //perform request to DB
}

fun updateDataInDB() {
  getIdTokenForUser()
  //wait till it finishes and then
  //perform request to DB
}

//......

我曾尝试阅读和实现协程,但我缺乏正确执行协程的知识.

I have tried reading about and implementing coroutines, but I lack the knowledge to do so correctly.

编辑

感谢@Doug Stevenson的回答和指导,我设法构造了以下内容:

Thanks to @Doug Stevenson for his answer and direction, I have managed to construct the following:

private suspend fun getUserIdToken(user: FirebaseUser) = coroutineScope {

    val job = async {
        user.getIdToken(false).result?.token
    }
    job.await()
}

我以这种方式使用它:

fun updateDB(context: Context) = runBlocking {

    val user = FirebaseAuth.getInstance().currentUser

    if (user != null) {
        val token = getUserIdToken(user)
    }

  }

这是正确的方法吗?由于以下给出的答案提出了不同的实现方式.

Is this the correct approach? Since the answers given below present a different implementation.

推荐答案

为了摆脱基于回调的API,如下所示:

In order to go from a callback based API like the following one:


val myCallback = object : ServiceCallback() {
    override fun onResult(theobject: Something) {
        // your callback code here
    }
    override fun onFailure(ex: Throwable) {
         // error handling
    }

}

theService.enqueue(callback)

您可以使用 suspendCoroutine

You can use suspendCoroutine

它的作用是暂停执行直到回调满足连续性.因此,您可以编写如下的KTX:

What it does is that it suspends execution until the continuation is satified by the callback. So you can write a KTX like the following:

suspend fun Service.getSomething(): Something = suspendCoroutine{ cont ->
    val callback = object : ServiceCallback(){
         override fun onSuccess(data: Something): Unit = cont.resume(data)
         override fun onFailure(ex: Throwable): Unit = cont.resume(ex)
    }
    this.enqueue(callback)
}

这篇关于如何在OnCompleteListener Firebase中使用异步/等待/协程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆