2016-09-19 4 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()이 발생하고 있으며 이런 종류의 보호를 제공 할 방법이 없습니다. 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 대 async (task)) 코드를 디스패치하지만 계산 된 값이 예외를 누설하지 않는지 확인하십시오. –

+0

제안 된 'Promise.of' 오버로드에 대해 우려하는 또 다른 사항은 이제 기능 타입이 'Promise <() -> V>'라는 약속을 원하지만 'Promise '이 표시되면 예기치 않게 발생합니다 – Ilya

관련 문제