2016-09-19 81 views
2

使用Kovenant,我有时会使用Promise.of(value)函数来创建一个同步结果,我想将其作为承诺进行包装。但有时调用,如:Kotlin在使用Kovenant Promise.of(value)时有时会发生异常

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

此代码失去第一承诺期间发生异常。他们去了哪里?他们从不记录。有时他们只是用未处理的异常来使我的应用程序崩溃。为什么这些诺言并没有抓住他们呢?

注:这个问题是故意书面和作者(Self-Answered Questions)回答,这样有趣的问题的解决方案在SO共享。

回答

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 { .. }块中看到您的异常记录。

+0

这似乎是使用'task'方法的替代方法:http://kovenant.komponents.nl/api/core_usage/#task。你能解释什么时候应该使用而不是'task'吗? – Ilya

+0

同步(Promise.of与异步(任务)调度代码,但要确保计算的值不会泄漏异常 –

+0

另一件与我提出的Promise.of'重载相关的事情是,现在它的行为意想不到的时候,想要承诺功能类型'Promise <() -> V>',但获得'Promise '而不是 – Ilya

相关问题