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

Swift Combine 序列请求执行完第一个就终止无法继续怎么解决?

问题根因

1. Cancellable 提前释放(概率最高)

你第二个请求发不出去的核心原因几乎都是订阅对应的 AnyCancellable 被提前释放了,对应到你的代码逻辑,问题出在请求的完成回调时序:
第一个请求完整的执行顺序是:

  1. 第一个请求拿到结果,先触发 receiveValue 闭包(因为加了 receiveOnMain,所以这个闭包被派发到主队列执行),你在这个闭包里调用 getData() 生成第二个请求的订阅,把第二个请求的 AnyCancellable 存入了 cancellableSet
  2. 紧接着第一个请求的 completion 闭包也被派发到主队列执行,如果你在 handleCompletion 方法里写了 cancellableSet.removeAll() 这类全局清空的逻辑,刚存进去的第二个请求的Cancellable会被立刻移除释放,对应的请求直接被取消,自然不会发起。

为什么去掉 receiveOnMain 就正常

没加 receiveOnMain 时,sink的两个闭包都会直接在URLSession的后台队列同步执行,要么是你的清空逻辑只在错误分支触发、这时候正常完成不会清空set,要么是时序差异下第二个请求已经发起完成才被释放,所以能看到请求正常执行,只是回调不在主线程报错。

2. 拼写错误

你代码里后两个请求的调度器方法拼写错误:正确写法是 receiveOnMain,你写成了 recieveOnMain(i和e顺序颠倒),如果你的扩展是按正确拼写实现的,写错的方法实际不存在,会导致整个订阅链无效,请求自然不会触发。

3. 调度器使用不规范

receive(on:) 只会影响它之后所有操作符的执行队列,和请求本身的发起队列无关。如果你之前错误的把 receiveOnMain 放在了订阅逻辑之前、导致订阅被派发到主队列执行出现了阻塞,也会出现请求发不出去的问题。

修复方案

  • 不要在单个请求的完成回调里全局清空 cancellableSet,可以单独持有每个请求的Cancellable,或者只在页面对象销毁的时候统一清空整个Set。
  • 修正所有 receiveOnMain 的拼写错误,保证方法被正确调用。
  • 不要移除 receive(on: .main) 逻辑,它可以保证你的sink闭包都在主线程执行,避免UI操作报错。如果需要优化请求性能,可以在请求Publisher的开头加上 subscribe(on: DispatchQueue.global()) 保证请求的订阅逻辑在后台队列执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 03:54:02