Kotlin协程-从暂停函数优雅地处理错误 [英] Kotlin coroutines - gracefully handling errors from suspend functions

查看:112
本文介绍了Kotlin协程-从暂停函数优雅地处理错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用从异步方法调用的暂停函数实现对错误的优雅处理,如何捕获由暂停方法引发的错误。

Trying to implement graceful handling of the errors with suspend functions that are called from async methods, How to catch the error thrown by a suspend method.

suspend fun findById(id: Long): User? {
    throw Exception("my exception") // intentionally throwing to simulate error situation.
    return userModel.findById(id) // IO, may throw an error
}

Caller件,使用IO线程启动

Caller piece, launching with IO thread

GlobalScope.launch(Dispatchers.IO) {
    try {

        var userAsync: Deferred<User?>? = null
        arguments?.getLong("id")?.let {
            userAsync = async { viewModel?.findById(it) } // async for efficiency as i've other async methods too.
        }

        val data = userAsync?.await()

        withContext(Dispatchers.Main) {
            user = data // data binding, populating UI fields of user
        }
    } catch (exception: Exception) {
        withContext(Dispatchers.Main) { fault(exception) }
    }
}

故障方法

private fun fault(exception: Exception) {
    Log.d("User", "fault: ${exception.localizedMessage}") // expecting output
}

当前运行时崩溃,想要实现错误的优雅处理。

Currently runtime is crashing, want to implement graceful handling of errors.

尝试2

尝试将尝试捕获放入异步块中,但它不喜欢它。

Tried placing try catch within the async block but it didn't like it.

var userAsync: Deferred<UserVO?>? = null
arguments?.getLong("id")?.let {
    userAsync = async {
        try {
            delegate?.findById(it)
        } catch (e: Exception) {
            print(e)
        }
    }
}


推荐答案

我将使用 CoroutineExceptionHandler 使协程正常失败:

I would use a CoroutineExceptionHandler to make your coroutines fail gracefully:

1)定义处理程序:

val exceptionHandler = CoroutineExceptionHandler { context, error ->
    // Do what you want with the error
    Log.d(TAG, error)
}

2)重构您的findById函数,使其在IO上下文中执行,并使您的ui代码成为主要安全对象:

suspend fun findById(id : Int) : User? = withContext(Dispatchers.IO){
    when(id){
        0 -> throw Exception("not valid")
        else -> return@withContext User(id)
    }
}



  1. MainScope 中启动您的工作(并因此更新ui),并传递exceptionHandler以启动协程生成器以捕获异常:

  1. Launch your job within MainScope (and so update the ui), passing exceptionHandler to launch coroutine builder in order to catch the exception:


val exceptionHandler = CoroutineExceptionHandler { _, error ->
     // Do what you want with the error
    Log.d(TAG, error)
}

MainScope().launch(exceptionHandler) {
     val user = delegate?.findById(userId)
        user?.let {
            Timber.v(it.toString())
        }
}

这篇关于Kotlin协程-从暂停函数优雅地处理错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆