runCatching

creativeBinΒ·2022λ…„ 12μ›” 26일
1

πŸ“£ runCatching 은 try-catch λ₯Ό λŒ€μ²΄ν•  수 μžˆλŠ” μ½”ν‹€λ¦°μ˜ 문법이닀.Β 

try-catch 문은 μ‹€νŒ¨μ‹œμ˜ 핸듀링을 μ²˜λ¦¬ν•  수 μžˆμ—ˆλ‹€λ©΄,

runCatching 은 성곡, μ‹€νŒ¨μ‹œ λ‘˜ λ‹€ 처리 ν•  수 μžˆλ‹€.

@InlineOnly
@SinceKotlin("1.3")
public inline fun <T, R> T.runCatching(block: T.() -> R): Result<R> {
    return try {
        Result.success(block())
    } catch (e: Throwable) {
        Result.failure(e)
    }
}

λ³΄λ‹€μ‹œν”Ό, 리턴 νƒ€μž…μ€ Result λΌλŠ” 객체이며,Β 

전달받은 λ‚΄μš©μ„ μ‹€ν–‰ν•΄μ„œ,Β 

μ„±κ³΅ν•œλ‹€λ©΄ Result.success() λ₯Ό 톡해 μ„±κ³΅ν–ˆλ‹€λŠ” λ‚΄μš©μ„ 담은 Result 객체,

μ‹€νŒ¨ν•œλ‹€λ©΄ Result.failure() λ₯Ό 톡해 μ—λŸ¬ λ‚΄μš©μ„ 담은 Result 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.


κΈ°λ³Έ 문법

runCatching { } : μ€‘κ΄„ν˜Έ μ•ˆμ— try ν•˜κ³ μž ν•˜λŠ” ꡬ문을 μž‘μ„±

onSuccess { } : μœ„ runCatch ꡬ문이 μ„±κ³΅μ‹œ 맀핑할 ꡬ문을 μž‘μ„±. it 은 μœ„ ꡬ문의 κ²°κ³Ό.

onFailure { } : μœ„ runCatch ꡬ문이 μ‹€νŒ¨μ‹œ 맀핑할 ꡬ문을 μž‘μ„±. it 은 μœ„ κ΅¬λ¬Έμ—μ„œ λ˜μ§„ Throwable 객체.

also { } : κΈ°μ‘΄ try-catch-finally μ—μ„œ finally μ—μ„œ μž‘μ„±ν•˜λ˜ ꡬ문을 μž‘μ„±ν•  수 있음.

λ³΅μž‘ν•œ 상황

map { } : μ„±κ³΅ν•œ 값에 λŒ€ν•΄ ν•œλ²ˆλ” 가곡이 κ°€λŠ₯. μ—¬κΈ°μ„œ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ©΄ runCatching ꡬ문 λ°–μœΌλ‘œ μ˜ˆμ™Έλ₯Ό 던짐.

mapCatching { } : μ„±κ³΅ν•œ 값에 λŒ€ν•΄ ν•œλ²ˆλ” 가곡이 κ°€λŠ₯. μ—¬κΈ°μ„œ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ©΄ runCatching ꡬ문 λ°–μœΌλ‘œ μ˜ˆμ™Έλ₯Ό λ˜μ§€μ§€ μ•Šκ³ , κ·Έ μ˜ˆμ™Έλ₯Ό 담은 Result 객체 λ°˜ν™˜. 이후 onFailure λ“±μœΌλ‘œ λ‹€μ‹œ μž‘μ•„μ„œ μ²˜λ¦¬κ°€λŠ₯.

recover { } : μ‹€νŒ¨ν•œ 값에 λŒ€ν•΄ ν•œλ²ˆλ” 핸듀링이 κ°€λŠ₯. μ—¬κΈ°μ„œ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ©΄ runCatching ꡬ문 λ°–μœΌλ‘œ μ˜ˆμ™Έλ₯Ό 던짐.

recoverCatching { } :μ‹€νŒ¨ν•œ 값에 λŒ€ν•΄ ν•œλ²ˆλ” 핸듀링이 κ°€λŠ₯. μ—¬κΈ°μ„œ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ©΄ runCatching ꡬ문 λ°–μœΌλ‘œ μ˜ˆμ™Έλ₯Ό λ˜μ§€μ§€ μ•Šκ³ , κ·Έ μ˜ˆμ™Έλ₯Ό 담은 Result 객체 λ°˜ν™˜. 이후 onFailure λ“±μœΌλ‘œ λ‹€μ‹œ μž‘μ•„μ„œ μ²˜λ¦¬κ°€λŠ₯.

runCatching ꡬ문의 return 값이 ν•„μš”ν• λ•Œ

getOrNull() : μœ„μ—μ„œ λ°˜ν™˜λœ Result 객체가 성곡객체 일 λ•Œ κ°’ λ°˜ν™˜. μ‹€νŒ¨λ©΄ null

getOrDefault(~) : μœ„μ—μ„œ λ°˜ν™˜λœ Result 객체가 성곡객체 일 λ•Œ κ°’ λ°˜ν™˜. μ‹€νŒ¨λ©΄ 뒀에 μ •μ˜ν•œ κ°’ λ°˜ν™˜.

getOrThrow() : μœ„μ—μ„œ λ°˜ν™˜λœ Result 객체가 성곡객체 일 λ•Œ κ°’ λ°˜ν™˜. μ‹€νŒ¨λ©΄ Result 객체의 μ˜ˆμ™Έ throw.

getOrElse { } : μœ„μ—μ„œ λ°˜ν™˜λœ Result 객체가 성곡객체 일 λ•Œ κ°’ λ°˜ν™˜. μ‹€νŒ¨λ©΄ 뒀에 μ •μ˜ν•œ ꡬ문 μ‹€ν–‰.

Result κ°μ²΄λŠ” ν•¨μˆ˜μ˜ λ°˜ν™˜ν˜•μœΌλ‘œ 쓰일 수 μ—†λ‹€.

Result<T>.getOrThrow(): T
Result<T>.getOrElse(onFailure: (exception: Throwable) -> R): R
Result<T>.getOrDefault(defaultValue: R): R
Result<T>.onSuccess(action: (value: T) -> Unit): Result<T>
Result<T>.onFailure(action: (exception: Throwable) -> Unit): Result<T>
Result<T>.fold(
    onSuccess: (value: T) -> R,
    onFailure: (exception: Throwable) -> R
): R

Result<T>.map(transform: (value: T) -> R): Result<R>
Result<T>.mapCatching(transform: (value: T) -> R): Result<R>
Result<T>.recover(transform: (exception: Throwable) -> R): Result<R>
Result<T>.recoverCatching(transform: (exception: Throwable) -> R): Result<R>

runCatching {
         doing...
      }.fold({
        // μ„±κ³΅μ‹œλ§Œ μ‹€ν–‰
      },{
        // μ‹€νŒ¨μ‹œλ§Œ μ‹€ν–‰
      })
            
var fruitName: String? = null
// μ‹€νŒ¨ μ‹œ default 값을 λ°˜ν™˜
fruitName = fruitResult.getOrDefault("")
// μ‹€νŒ¨ μ‹œ else block의 결괏값을 λ°˜ν™˜
fruitName = fruitResult.getOrElse {
    when(it) {
        is IllegalStateException -> "Sold out"
        is NullPointerException -> "null"
        else -> throw it
    }
}
// μ‹€νŒ¨μ‹œ throwable이 λ‹€μ‹œ throw 
fruitName = fruitResult.getOrThrow()

// map, recover을 μ΄μš©ν•΄ 성곡과 μ‹€νŒ¨ μ‹œ μ›ν•˜λŠ” κ°’μœΌλ‘œ λ°”κΏ€ 수 있음
fruitResult.map {
    it.toUpperCase()
}

// Exception λ³„λ‘œ λ‹€μ‹œ ν•œλ²ˆ 더 핸듀링이 κ°€λŠ₯
fruitResult.recover {
    when(it) {
        is IllegalStateException -> "Sold out"
        is NullPointerException -> "null"
        else -> throw it
    }
}

참고자료

https://uchun.dev/runCatching%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-kotlin%EC%97%90%EC%84%9C-exception%EC%B2%98%EB%A6%AC-%EB%B0%A9%EB%B2%95/

profile
μ–Έμ œλ‚˜ 항상 즐겁게 New vibes 😎

0개의 λŒ“κΈ€