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

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

SyncService - > Sync Feature - > Feature Repository - > DataSource

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

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()
}

它确实按顺序执行它,但我需要一种方法来阻止其他任何协程,如果有任何错误 . 只有来自Apollo的错误's So I'已经尝试了很多方法来找到简化这段代码的方法,但是甚至不知道这种回调的链接是否可以简化 . 这就是为什么我来这里看一些想法 . TLDR: 我想要一种顺序执行所有函数的方法,并且如果有任何异常没有很多链接回调,仍然能够停止所有协同程序 .