반응형
코루틴의 callbackFlow 에서 sendBlocking 이 Deprecated가 되었다. 그럼 어떻게 써야하는가?
trySendBlocking 로 변경해서 사용하면 된다.
그럼 무슨 차이가 있을까?
코드에 적혀있는 설명을 보면
trySendBlocking은
Adds element into to this channel, blocking the caller while this channel is full, and returning either successful result when the element was added, or failed result representing closed channel with a corresponding exception.
This is a way to call Channel.send method in a safe manner inside a blocking code using runBlocking and catching, so this function should not be used from coroutine.
Example of usage:
// From callback API
channel.trySendBlocking(element)
.onSuccess { /* request next element or debug log */}
.onFailure { t: Throwable? -> /* throw or log */}
For this operation it is guaranteed that failure always contains an exception in it.
sendBlocking 은
Deprecated blocking variant of send. This method is deprecated in the favour of trySendBlocking.
sendBlocking is a dangerous primitive — it throws an exception if the channel was closed or, more commonly, cancelled. Cancellation exceptions in non-blocking code are unexpected and frequently trigger internal failures.
These bugs are hard-to-spot during code review and they forced users to write their own wrappers around sendBlocking. So this function is deprecated and replaced with a more explicit primitive.
The real-world example of broken usage with Firebase:
callbackFlow {
val listener = object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
// This line may fail and crash the app when the downstream flow is cancelled
sendBlocking(DataSnapshot(snapshot))
}
override fun onCancelled(error: DatabaseError) {
close(error.toException())
}
}
firebaseQuery.addValueEventListener(listener)
awaitClose { firebaseQuery.removeEventListener(listener) }
}
즉, sendBlocking은 채널이 닫혔거나 더 일반적으로 취소된 경우 예외가 발생합니다. 또한 non-blocking code의 취소 예외는 예상치 못한 것이며 자주 내부 오류를 유발합니다.
그런 오류를 잡아주도록 개발된 코드가 trysendBlocking 입니다
반응형