我正在尝试使用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: 我想要一种顺序执行所有函数的方法,并且如果有任何异常没有很多链接回调,仍然能够停止所有协同程序 .