AsyncSubject

โณ AsyncSubject โ€” ์™„๋ฃŒ ์‹œ์ ์˜ โ€˜๋งˆ์ง€๋ง‰ ๊ฐ’โ€™๋งŒ ๋ฐฉ์ถœ

ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ: Single Emission at Completion ยท Hot Subject ยท Single-result Tasks

AsyncSubject<Element>๋Š” ์ŠคํŠธ๋ฆผ์ด ์™„๋ฃŒ๋  ๋•Œ ๋‹จ ํ•œ ๋ฒˆ, ๋งˆ์ง€๋ง‰ onNext ๊ฐ’๋งŒ ์ „ํŒŒํ•ฉ๋‹ˆ๋‹ค. ์™„๋ฃŒ ์ „์— ๊ตฌ๋…ํ•ด๋„ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์ง€ ๋ชปํ•˜๋‹ค๊ฐ€, .onCompleted() ํ˜ธ์ถœ ์ˆœ๊ฐ„ ์ตœ์‹  ๊ฐ’ 1๊ฐœ๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ์ŠคํŠธ๋ฆผ์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.


1๏ธโƒฃ ํŠน์ง• ์š”์•ฝ

ํ•ญ๋ชฉ
๋‚ด์šฉ

์ดˆ๊ธฐ๊ฐ’

โŒ ์—†์Œ

์บ์‹œ ํฌ๊ธฐ

1 (๋งˆ์ง€๋ง‰ ๊ฐ’, ์™„๋ฃŒ ์‹œ)

๊ตฌ๋… ์‹œ ์ „๋‹ฌ

์™„๋ฃŒ ์ „ โ†’ ์—†์Œ / ์™„๋ฃŒ ํ›„ โ†’ ๋งˆ์ง€๋ง‰ ๊ฐ’๊ณผ .completed

์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ

.onCompleted() ํ•„์ˆ˜ (์—๋Ÿฌ ์‹œ .error๋งŒ ์ „ํŒŒ)


2๏ธโƒฃ ๊ธฐ๋ณธ ์‚ฌ์šฉ ์˜ˆ์ œ

let subject = AsyncSubject<String>()
let bag = DisposeBag()

subject.onNext("Step 1")
subject.onNext("Step 2")

subject.subscribe(onNext: { print("Subscriber:",$0) },
                  onCompleted: { print("Completed!") })
    .disposed(by: bag)

subject.onNext("Final Step")
subject.onCompleted()

์ถœ๋ ฅ

Subscriber: Final Step
Completed!
  • โ€˜Final Stepโ€™๋งŒ ๋ฐฉ์ถœ๋จ (๋งˆ์ง€๋ง‰ onNext).

  • onCompleted()๊ฐ€ ์—†์œผ๋ฉด ์˜์›ํžˆ ๋ฌด์‘๋‹ต์ด๋ฏ€๋กœ ๋ฐ˜๋“œ์‹œ ํ˜ธ์ถœ.


3๏ธโƒฃ ์‹ค์ „ ํŒจํ„ด โ€” ํŒŒ์ผ ์—…๋กœ๋“œ ๊ฒฐ๊ณผ ์ „๋‹ฌ

func uploadFile(_ data: Data) -> Observable<UploadResponse> {
    let subject = AsyncSubject<UploadResponse>()

    api.upload(data: data) { result in
        switch result {
        case .success(let response):
            subject.onNext(response) // ๋งˆ์ง€๋ง‰ ๊ฒฐ๊ณผ
            subject.onCompleted()
        case .failure(let error):
            subject.onError(error)
        }
    }

    return subject.asObservable() // ํ˜ธ์ถœ ์ธก: ๊ฒฐ๊ณผ 1๊ฐœ๋งŒ ์ˆ˜์‹ 
}
  • ์—ฌ๋Ÿฌ ์ค‘๊ฐ„ ์ง„ํ–‰๋ฅ ์ด ํ•„์š”ํ•˜๋ฉด PublishSubject๋กœ ๋”ฐ๋กœ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ.


4๏ธโƒฃ Subject ๋น„๊ต ํ…Œ์ด๋ธ”

Subject
๋ฐœํ–‰ ์‹œ์ 
๋ฐฉ์ถœ ๊ฐœ์ˆ˜
์‚ฌ์šฉ ์‚ฌ๋ก€

PublishSubject

onNext ์ฆ‰์‹œ

N

๋ฒ„ํŠผ ํƒญ

BehaviorSubject

onNext ์ฆ‰์‹œ + ์บ์‹œ 1

N

์ƒํƒœ ์ €์žฅ

ReplaySubject

onNext ์ฆ‰์‹œ + ์บ์‹œ N

N

์ฑ„ํŒ… ํžˆ์Šคํ† ๋ฆฌ

AsyncSubject

onCompleted ์‹œ

1

๋น„๋™๊ธฐ ์ž‘์—… ์ตœ์ข… ๊ฒฐ๊ณผ


5๏ธโƒฃ ์—๋Ÿฌ ์ฒ˜๋ฆฌ & Empty ์‹œ๋‚˜๋ฆฌ์˜ค

  • .onError(e) ํ˜ธ์ถœ ์‹œ ๊ฐ’ ์—†์ด ์—๋Ÿฌ๋งŒ ์ „๋‹ฌ.

  • ์™„๋ฃŒ ์ „์— onNext๊ฐ€ ํ•œ ๋ฒˆ๋„ ์—†์—ˆ๋‹ค๋ฉด ๊ตฌ๋…์ž๋Š” completed๋งŒ ์ˆ˜์‹ (๊ฐ’=nil).

subject.onCompleted() // next ์—†์—ˆ๋‹ค๋ฉด completed ์ด๋ฒคํŠธ๋งŒ ์ „๋‹ฌ

6๏ธโƒฃ Mini Quiz

  1. AsyncSubject์— ๊ฐ’์„ 3๊ฐœ ๋ณด๋‚ด๊ณ  .onCompleted()๋ฅผ ์ƒ๋žตํ•˜๋ฉด ๊ตฌ๋…์ž๋Š” ๋ฌด์—‡์„ ๋ฐ›๋Š”๊ฐ€?

  2. RxSwift์˜ Single<Element>์™€ AsyncSubject ๊ธฐ๋Šฅ ์ฐจ์ด ํ•œ ์ค„ ์š”์•ฝ.

  3. Combine ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์œ ์‚ฌํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์–ด๋–ค Combine ๊ฐ์ฒด๋‚˜ ์˜คํผ๋ ˆ์ดํ„ฐ ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ ๊นŒ?

์ •๋‹ต
  1. ์•„๋ฌด ๊ฒƒ๋„ ๋ฐ›์ง€ ๋ชปํ•œ๋‹ค. ์ŠคํŠธ๋ฆผ์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ๊ฐ€ ์ „ํŒŒ๋˜์ง€ ์•Š๋Š”๋‹ค.

  2. Single์€ ์™„๋ฃŒ ๋˜๋Š” ์—๋Ÿฌ๋ฅผ ์ž๋™ ๊ด€๋ฆฌํ•˜๋Š” cold ๋‹จ๋ฐœ ์ŠคํŠธ๋ฆผ ํŒฉํ† ๋ฆฌ, AsyncSubject๋Š” hot subject๋กœ ์ง์ ‘ onNext/onCompleted ์ œ์–ด ๊ฐ€๋Šฅ.

  3. Combine์—์„œ๋Š” PassthroughSubject + .last() ์˜คํผ๋ ˆ์ดํ„ฐ ๋˜๋Š” Future๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™„๋ฃŒ ์‹œ ๋‹จ์ผ ๊ฐ’ ์ „๋‹ฌ ํŒจํ„ด์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.


๋‹ค์Œ โ–ถ๏ธ schedulers.md ๋กœ ์ด๋™ํ•ด ์Šค๋ ˆ๋“œยท์‹คํ–‰ ์ปจํ…์ŠคํŠธ ์ œ์–ด๋ฅผ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค. ๐Ÿš€

Last updated