如何在Observable的flatMap链式调用中获取所有前置结果?
Hey there! Let’s tackle this common RxSwift scenario—you’ve got a chain of dependent flatMap calls, and you want to access all the previous responses when you get to the final subscription. Here are two straightforward, clean approaches to make that happen:
Option 1: Use Tuples to Carry Forward Responses
Tuples are a quick way to bundle up previous responses without extra boilerplate. Each flatMap step will wrap the prior response(s) along with the new one:
// Assuming you have a disposeBag defined somewhere let disposeBag = DisposeBag() getObservable1() // First flatMap: Pair API1 response with API2 response .flatMap { api1Response -> Observable<(API1Response, API2Response)> in getObservable2(param: api1Response) .map { api2Response in (api1Response, api2Response) } } // Second flatMap: Add API3 response to the tuple .flatMap { (api1, api2) -> Observable<(API1Response, API2Response, API3Response)> in getObservable3(param: api2) .map { api3Response in (api1, api2, api3Response) } } .subscribe(onNext: { api1, api2, api3 in // Now you have access to all three responses! print("Got API1 response: \(api1)") print("Got API2 response: \(api2)") print("Got API3 response: \(api3)") }) .disposed(by: disposeBag)
This approach is perfect for short chains (3-4 steps max) because tuples stay readable. The downside is that tuples get unwieldy if you need to add more steps later.
Option 2: Use a Custom Struct for Better Readability
If you anticipate extending the chain or want cleaner code, define a struct to encapsulate all your responses. This makes the code more maintainable and self-documenting:
First, create the struct:
struct CombinedAPIResponses { let api1: API1Response let api2: API2Response let api3: API3Response }
Then adjust your Rx chain to populate this struct:
let disposeBag = DisposeBag() getObservable1() .flatMap { api1 in getObservable2(param: api1) .map { api2 in (api1, api2) } } .flatMap { (api1, api2) in getObservable3(param: api2) .map { api3 in CombinedAPIResponses(api1: api1, api2: api2, api3: api3) } } .subscribe(onNext: { combinedResponses in // Access responses via the struct's properties print("API1 data: \(combinedResponses.api1)") print("API2 data: \(combinedResponses.api2)") print("API3 data: \(combinedResponses.api3)") }) .disposed(by: disposeBag)
Structs shine here because they give you named properties (no guessing which tuple element is which) and are easy to extend if you add a getObservable4 later.
Key Notes
- Both approaches preserve the dependent sequence flow:
getObservable2only runs aftergetObservable1completes, andgetObservable3only runs aftergetObservable2completes. - Avoid trying to use
scanfor this scenario—scanis for accumulating values from a sequence, but your chain relies on each step’s output to trigger the next request, whichflatMaphandles perfectly.
Hope this solves your problem! 😊
内容的提问来源于stack exchange,提问作者13thang08

