如何等待所有嵌套的异步函数在 Kotlin 中完成?

huangapple go评论72阅读模式
英文:

How to wait for all nested async functions to complete in Kotlin?

问题

Here's the translated code portion:

我在Android移动应用程序中有以下代码 我需要确保transaction.save()在调用dismiss()之前始终执行完成 目前它只有在某些情况下才能正常工作 我感谢有关如何重构此代码以使其按照我期望的方式运行的任何建议

private fun save() {
lifecycleScope.launch {
showLoader()
withContext(Dispatchers.IO) {
transaction.save()
}
dismiss()
}
}


transaction.save()方法的定义。 onTripEvent是另一个挂起函数,用于保存记录在设备数据库中,并将其发送到Web API。 我不会提供它的定义。

suspend fun save() {
tripRepository.updateTripSourceItem(this)
tripRepository.onTripEvent("Updated item etc.")
}


tripRepository.updateTripSourceItem的定义

suspend fun updateTripSourceItem(tripSourceItem: TripSourceItem) {
localDataSource.updateTripSourceItem(tripSourceItem)
api.putTripSourceItem(tripSourceItem).await()
}


localDataSource.updateTripSourceItem的定义

@Dao
interface TripDao {
@Update
suspend fun updateTripSourceItem(tripSourceItem: TripSourceItem)
}


api.putTripSourceItem的定义

interface api {
@POST("apiEndPoint")
fun putTripSourceItem(
@Body body: TripSourceItem
): Deferred<List>
}


我知道在访问数据库时最佳实践是使用withContext(Dispatchers.IO),但我应该在哪个函数中使用它?是顶级的`save()`函数,`transaction.save()`,`tripRepository.updateTripSourceItem()`,还是都是?我考虑过在每个函数中都添加类似以下内容,但这似乎有些过度。

suspend fun save()
withContext(Dispatchers.IO) {
awaitAll(
async { tripRepository.updateTripSourceItem(this@TripSourceItem) },
async { tripRepository.onTripEvent("Updated item etc.") }
)
}
}
}

英文:

I have the following code in an Android mobile app. I need to make sure transaction.save() is always finished executing before dismiss() is called. Currently, it only works some of the time. I appreciate any advice on how to restructure this to run like I expect it to.

private fun save() {
   lifecycleScope.launch {
      showLoader()
      withContext(Dispatchers.IO) {
         transaction.save()
      }
      dismiss()
   }
}

Definition of transaction.save() method. onTripEvent is another suspend function that saves a record in the device database, and sends it to a web API. I won't bother providing its definition.

suspend fun save() {
   tripRepository.updateTripSourceItem(this)
   tripRepository.onTripEvent(&quot;Updated item etc.&quot;)
}

Definition of tripRepository.updateTripSourceItem

suspend fun updateTripSourceItem(tripSourceItem: TripSourceItem) {
   localDataSource.updateTripSourceItem(tripSourceItem)
   api.putTripSourceItem(tripSourceItem).await()
}

Definition of localDataSource.updateTripSourceItem

@Dao
interface TripDao {
   @Update
   suspend fun updateTripSourceItem(tripSourceItem: TripSourceItem)
}

Definition of api.putTripSourceItem

interface api {
   @POST(&quot;apiEndPoint&quot;)
   fun putTripSourceItem(
      @Body body: TripSourceItem
   ): Deferred&lt;List&lt;StatusResponse&gt;&gt;
}

I know it's best practice to use withContext(Dispatchers.IO) when accessing the database, but which function do I need that in? The top level save() function, transaction.save(), tripRepository.updateTripSourceItem(), or all of the above? I thought about putting something like this in every function, but it seems like overkill.

suspend fun save()
   withContext(Dispatchers.IO) {
         awaitAll(
             async { tripRepository.updateTripSourceItem(this@TripSourceItem) },
             async { tripRepository.onTripEvent(&quot;Updated item etc.&quot;) }
         )
      }
   }
}

答案1

得分: 1

你在你的DAO的updateTripSourceItem中使用了suspend。这样做就是在告诉Room:“请在你自己的时间里做这个,不要打扰我或让我等待”。

由于你想要等待数据库正确更新,移除suspend就能解决问题,你就不需要用await写样板代码。

英文:

You are using suspend in your updateTripSourceItem in your DAO.
When doing that, you are saying to Room "Make sure you do this at your own time, don't bother me or make me wait"

Since you want to wait until the database is properly updated, removing the suspend will do the trick and you won't need to do boilerplate code with awaits

答案2

得分: -2

Wrap the save call with async.

private fun save() {
    lifecycleScope.launch {
        showLoader()
        async(Dispatchers.IO) {
            transaction.save()
        }.await()
        dismiss()
    }
}
英文:

Wrap the save call with async.

private fun save() {
    lifecycleScope.launch {
        showLoader()
        async(Dispatchers.IO) {
            transaction.save()
        }.await()
        dismiss()
    }

huangapple
  • 本文由 发表于 2023年5月18日 00:11:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76274128.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定