Kotlin Coroutine逃脱回调地狱

时间:2018-02-20 02:48:54

标签: android callback kotlin apollo kotlinx.coroutines

我正在尝试使用Kotlin的协同程序来避免回调地狱,但在这种特殊情况下它看起来并不像我能想到的那样。我希望能有一些关于它的事情。

我有这个SyncService类,它调用一系列不同的方法将数据发送到服务器,如下所示: SyncService调用Sync Student,它调用Student Repository,它调用DataSource,使服务器请求通过Apollo的Graphql Client发送数据。 我的每个功能都遵循相同的模式:

  

SyncService - >同步功能 - >功能存储库 - >数据源

所以我调用的每个方法都有这个签名:

fun save(onSuccess: ()-> Unit, onError:()->Unit) {
  //To Stuff here
}

问题是: 当我在服务器上同步并成功保存学生时,我需要同步他的注册,如果我成功保存了注册,我需要同步另一个对象,依此类推。 这一切都取决于彼此,我需要按顺序执行,这就是我使用回调的原因。 但是你可以想象,代码结果不是很友好,我和我的团队开始寻找替代方案以保持更好。我们最终得到了这个扩展功能:

suspend fun <T> ApolloCall<T>.execute() = suspendCoroutine<Response<T>> { cont ->
enqueue(object: ApolloCall.Callback<T>() {
    override fun onResponse(response: Response<T>) {
        cont.resume(response)
    }

    override fun onFailure(e: ApolloException) {
        cont.resumeWithException(e)
    }
})
}

但是DataSource中的函数仍然有onSuccess()和onError()作为回调,需要传递给任何调用它的人。

 fun saveStudents(
        students: List<StudentInput>,
        onSuccess: () -> Unit,
        onError: (errorMessage: String) -> Unit) {

    runBlocking {

        try {
            val response = GraphQLClient.apolloInstance

                    .mutate(CreateStudentsMutation
                            .builder()
                            .students(students)
                            .build())
                    .execute()

            if (!response.hasErrors())
                onSuccess()
            else
                onError("Response has errors!")

        } catch (e: ApolloException) {
            e.printStackTrace()
            onError("Server error occurred!")
        }
    }
}

SyncService类代码更改为:

 private fun runSync(onComplete: () -> Unit) = async(CommonPool) {

    val syncStudentProcess = async(coroutineContext, start = CoroutineStart.LAZY) {
        syncStudents()
    }

    val syncEnrollmentProcess = async(coroutineContext, start = CoroutineStart.LAZY) {
        syncEnrollments()
    }

    syncStudentProcess.await()
    syncEnrollmentProcess.await()

    onComplete()
}

它会按顺序执行它,但如果有任何错误,我需要一种方法来阻止其他所有协程。错误可能只来自阿波罗的 所以我一直在努力寻找一种简化代码的方法,但没有得到任何好的结果。我甚至不知道这种回调的链接是否可以简化。这就是为什么我来这里看一些想法。 TLDR:我想要一种顺序执行所有函数的方法,并且如果有任何异常没有很多链接回调,仍然能够停止所有协同程序。

0 个答案:

没有答案