RxSwift如何等待Observable完成后依次执行操作?
Hey there! I totally get where you're coming from as a RxSwift newbie—getting the hang of all those operators can feel overwhelming at first. Let's fix your sequential execution issue right away.
The Problem with Your Current Code
When you use map here:
let something = actions.map { action in return do(action) }
You end up with an Observable<Observable<Result>> (a stream of streams). If you subscribe to this, all the inner observables (from do(action: "do1"), do(action: "do2"), etc.) will start in parallel instead of waiting for the previous one to finish. That's why you're not seeing the sequential execution you want.
The Fix: Use concatMap Instead of map
To make each action run only after the previous one completes, swap out map for concatMap. This operator handles exactly what you need—it subscribes to each inner observable one at a time, waiting for the current one to finish before moving on to the next.
Here's the updated code:
let something = actions.concatMap { action in return self.do(action: action) // Don't forget `self` if this is in a class/struct }
Alternative: Use concat() on Your Stream of Streams
If you already have an Observable<Observable<Result>> (like the one from your original map call), you can also use the concat() operator to flatten it into a single sequential stream:
let something = actions.map { action in return self.do(action: action) }.concat()
This does the same thing as concatMap—just a slightly different approach depending on your use case.
Important Note: Ensure Inner Observables Complete
For concatMap or concat() to work correctly, each do(action:) call must return an observable that emits a completed event once its task is done. If your observable never completes, the sequence will get stuck on that first action forever.
For example, if you're simulating an async task, make sure to send onCompleted() after your result:
enum Result { case success case failure(Error) } func do(action: String) -> Observable<Result> { return Observable.create { observer in // Simulate async work (e.g., network call, file operation) DispatchQueue.global().asyncAfter(deadline: .now() + 1) { print("Finished executing \(action)") observer.onNext(.success) observer.onCompleted() // Critical for sequential execution! } return Disposables.create() } }
Testing It Out
When you subscribe to something, you'll see the print statements in order:
Finished executing do1 Finished executing do2 Finished executing do3
Perfect—exactly the sequential flow you wanted!
内容的提问来源于stack exchange,提问作者buhutz

