简体   繁体   中英

Why RxSwift concat with multiple observables does not seem to work?

My RxSwift code is,

func testOperators(){

    let bag = DisposeBag()

    let observable1 = PublishSubject<String>()
    let observable2 = PublishSubject<String>()

    Observable.concat([observable1, observable2])
        .subscribe(onNext: { (value) in
            print(value)
        }).disposed(by: bag)

    observable1.on(.next("1"))
    observable1.on(.next("2"))

    observable2.on(.next("3"))
    observable2.on(.next("4"))

    observable1.on(.completed)
    observable2.on(.completed)
}

Current output is,

1
2

My expected output is,

1
2
3
4

What am I missing & what I can add/edit to get the expected output?

You are emitting "3" and "4" before the concat has subscribed to observable2. concat hasn't subscribed to observable2 yet because it's waiting for observable1 to complete. By the time concat subscribes to observable2, the "3" and "4" event are gone.

As an analogy: imagine you have two people throwing balls and you have one catcher. You have told the catcher to catch all the balls from the first thrower, then switch to the second thrower. The first thrower throws two balls to the catcher, the second thrower throws two balls to nobody because the catcher is waiting to see if the first thrower is going to throw any more balls. Then the first thrower tells the catcher he's done throwing balls. The catcher then starts watching the second thrower, who says he's done too. In the end, the catcher only caught two balls.

If you were to turn observable2 into a ReplaySubject that had a large enough buffer, then it would replay all the events it received for each subscriber and you would get the output you wanted.

    let bag = DisposeBag()

    let observable1 = PublishSubject<String>()
    let observable2 = PublishSubject<String>()

    Observable.concat([observable1, observable2])
        .subscribe(onNext: { (value) in
            print(value)
        }).disposed(by: bag)

    observable1.on(.next("1"))
    observable1.on(.next("2"))
    observable1.on(.completed) //observable1 emission has been completed here.


    //so now observable2 emission will start here
    observable2.on(.next("3"))
    observable2.on(.next("4"))
    observable2.on(.completed) //observable2 emission has been completed here.

This will give you your expected output, I hope this will help :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM