You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift Combine连续发起两个网络请求异常,未得到期望的BandModel

Combine链式请求问题:输出Publisher实例而非BandModel

我是Combine新手,尝试依次发起两个网络请求。编写了fetchData2方法、UserServiceProtocol协议,以及TokenModel、BandModel结构体,但运行后输出的是Publisher实例,而非期望的BandModel,请问我遗漏了什么?

当前输出:<PublisherBox<Decode<TryMap<SubscribeOn<DataTaskPublisher, OS_dispatch_queue>, Data>, BandModel, JSONDecoder>>: 0x600002911ce0>


代码实现

fetchData2方法

func fetchData2() {
    loading = true
    print("👻 fetchData")
    
    _ = userService.getToken()
        .receive(on: RunLoop.main)
        .map { $0 }
        .compactMap { self.userService.getBand(token: $0.access_token) }
        .map { $0 }
        .sink(receiveCompletion: { [weak self] _ in
            self?.loading = false
        },receiveValue: { [weak self] result in
            self?.loading = false
            print(result)
        })
}

UserServiceProtocol协议

protocol UserServiceProtocol {
func getToken() -> AnyPublisher<TokenModel, Error>
func getBand(token: String)  -> AnyPublisher<BandModel, Error>
}

模型定义

struct TokenModel: Codable {
var access_token: String
var token_type: String
var expires_in: Int
}

struct BandModel: Codable {
var external_urls: External
var followers: Follower
var genres: [String]
var href: String
var id: String
var images: [ImageCode]
var name: String
var popularity: Int
var type: String
var uri: String
}

问题原因与解决方法

问题出在**compactMap的误用**:userService.getBand(token:)返回的是AnyPublisher<BandModel, Error>,compactMap会直接把这个Publisher实例作为值传递给下游,导致sink的receiveValue拿到的是Publisher而非BandModel。

要实现顺序执行的链式网络请求,你需要用**flatMap**替代compactMap:

  • flatMap会自动订阅内部返回的Publisher,将它发出的实际值(也就是BandModel)传递给下游,而非传递Publisher本身。

修改后的fetchData2代码:

func fetchData2() {
    loading = true
    print("👻 fetchData")
    
    _ = userService.getToken()
        .receive(on: RunLoop.main)
        // 替换compactMap为flatMap
        .flatMap { self.userService.getBand(token: $0.access_token) }
        .sink(receiveCompletion: { [weak self] _ in
            self?.loading = false
        },receiveValue: { [weak self] result in
            self?.loading = false
            print(result) // 现在将输出BandModel实例
        })
}

另外,原代码中两个map { $0 }属于冗余代码,它们只是原样传递值,没有实际作用,可以直接删除以简化逻辑。


内容的提问来源于stack exchange,提问作者ironRoei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:01:21