在Kotlin使用Kovenant Promise.of(值)时,我有时会泄漏异常

时间:2016-09-19 03:34:40

标签: kotlin kovenant

使用Kovenant,我有时会使用Promise.of(value)函数创建一个我希望包装为promise的同步结果。但有时会这样称呼:

Promise.of(callSomeCalculation())  <-- throws exception sometimes
  .then { ... }
  .then { ... }
  .fail { ex -> log.error(ex) }    <-- exception is not logged

此代码丢失了第一个承诺期间发生的异常。他们去哪儿了?它们永远不会被记录。有时他们只是用未处理的异常来崩溃我的应用程序。为什么承诺没有抓住他们所有人?

注意: 此问题是由作者(Self-Answered Questions)故意编写和回答的,因此可以在SO中分享有趣问题的解决方案。

1 个答案:

答案 0 :(得分:2)

问题是你在承诺链之外泄露异常。想象一下这段代码:

fun makeMyPromise(): Promise<Int, Exception> {
    val result: Int = callSomeCalculation()  // <--- exception occurs here
    val deferred = deferred<Int, Exception>()
    deferred.resolve(result)
    return deferred.promise
}

这基本上是您的代码在第一行中所做的事情。如果抛出异常,则该方法将以异常退出,并且永远不会调用deferred.reject。将代码更改为:

fun makeMyPromise(): Promise<Int, Exception> {
    val deferred = deferred<Int, Exception>()
    try {
        val result: Int = callSomeCalculation()  // <--- exception occurs here
        deferred.resolve(result)
    } catch (ex: Exception) {
        deferred.reject(ex)
    }
    return deferred.promise
}

会更正确并抓住你的例外。并且它确保没有任何东西可以从承诺链泄漏。

回到原始代码,callSomeCalculation()正在调用Promise.of()方法之前发生,并且无法提供此类保护。它发生在Kovenant有一个想法,你甚至创造了一个承诺。因此,您需要一个新的Promise.of(lambda)方法,该方法接受可以完全防止此类泄漏的代码块。

这是一个新的Promise.of(lambda)扩展功能:

fun <V> Promise.Companion.of(codeBlock: () -> V): Promise<V, Exception> {
    val deferred = deferred<V, Exception>()
    try {
        deferred.resolve(codeBlock())
    }
    catch (ex: Exception) {
        deferred.reject(ex)
    }
    return deferred.promise
}

将用作:

Promise.of { callSomeCalculation() }   <-- sometimes throws exception
  .then { ... }
  .then { ... }
  .fail { ex -> log.error(ex) }        <-- exception ALWAYS logged!

请注意,括号()已更改为{}括号,因为现在代码块已传递到Promise.of方法并包含异常处理,以防止任何泄漏。现在,您将在后面的fail { .. }块中看到您的异常。