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

使用Kovenant,我Promise.of(value)使用Promise.of(value)函数来创建一个同步结果,我想把它作为一个承诺来包装。 但是有时候会这样叫:

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

这段代码丢失了在第一次承诺期间发生的异常。 他们去了哪里? 他们从不记录。 有时他们只是崩溃我的应用程序与未处理的异常。 为什么这个承诺不能抓住他们呢?

注意: 这个问题是由作者故意编写和回答的( 自我回答问题 ),所以在SO中共享有趣问题的解决方案。

问题在于你在承诺链外泄漏了例外。 想象一下这段代码:

 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 { .. }块中。