挂起函数返回太早

问题描述 投票:0回答:1

我有以下功能,它完全是异步的 2 个任务,用于将数据上传到 Firebase。 我需要第二个函数来返回在 Firebase 中创建的新文档的 documentId,完成后主函数返回此 documentId,以便我可以在其他地方使用它。 但是,返回函数在 Firebase 上传异步函数运行之前完成,因此返回空字符串。 我该如何解决这个问题?

suspend fun profileLiked(): String {

var documentId: String = ""

CoroutineScope(Dispatchers.IO).launch {
    supervisorScope {

        try {
            async {
                firstFunctionToUploadAysnchronouslyToFirebase()
            }.await()


            async {
                documentId = secondFunctionToUploadAsynchronouslyToFirebase()
            }.await()

        } catch (error: Exception) {
            throw error
        }
    }
}

//this return function is getting called first and returning the empty string instead of the documentId result from secondFunctionToUploadAsynchronouslyToFirebase()
return documentId
}
firebase kotlin async-await return
1个回答
0
投票

上面的代码没有问题,它正在做它想要的事情。
如果您需要从

secondFunctionToUploadAsynchronouslyToFirebase
返回的 documentId,那么您需要在返回 documentId 之前等待父协程。
附加信息添加为评论。

suspend fun profileLiked(): String {

    var documentId: String = ""
    val job = CoroutineScope(Dispatchers.IO).launch { // This will create a new coroutine
      supervisorScope {
        try {
          async {    // another async coroutine within parent coroutine
            firstFunctionToUploadAysnchronouslyToFirebase()
          }
          async {    // another async coroutine within parent coroutine 
            documentId = secondFunctionToUploadAsynchronouslyToFirebase()
          }
        } catch (error: Exception) {
          throw error
        }
      }
    }
    job.join() // This will wait until all children of parent coroutines are executed.
    return documentId
  }
  1. 如果你不想使用job.join,那么我们可以将代码修改为
  suspend fun profileLiked(): String {

    var documentId: String = ""
    supervisorScope {    // Ref: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/supervisor-scope.html
      try {
        val c1 = async(Dispatchers.Default) {    // another async coroutine within parent coroutine, you can skip using `Dispatchers.Default`  
          firstFunctionToUploadAysnchronouslyToFirebase()
        }
        val c2 = async(Dispatchers.Default) {   // another async coroutine within parent coroutine, you can skip using `Dispatchers.Default`
          documentId = secondFunctionToUploadAsynchronouslyToFirebase()
        }
        listOf(c1, c2).awaitAll()
      } catch (error: Exception) {
        throw error
      }
    }
    return documentId
  }
© www.soinside.com 2019 - 2024. All rights reserved.