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

Swift/Combine环境下顺序执行两个Future异步任务的实现方案

实现方案

优化API签名后的优雅实现(推荐)

原有嵌套Result的写法没有利用Combine原生的错误处理能力,小幅调整签名后代码更简洁易维护,也完全满足顺序执行的需求。

调整后的函数签名

import Combine

func firstCall() -> Future<Void, Error> {
    return Future { promise in
        // 成功走.success,失败走.failure即可
        promise(.success(()))
    }
}

func secondSynchronousCall() throws {
    // 原有同步逻辑
}

private func secondCall() -> Future<Void, Error> {
    return Future { [weak self] promise in
        guard let self = self else {
            promise(.failure(NSError(domain: "InstanceReleased", code: -1, userInfo: nil)))
            return
        }
        do {
            try self.secondSynchronousCall()
            promise(.success(()))
        } catch {
            promise(.failure(error))
        }
    }
}

工具方法实现

// 按顺序执行任务队列,前一个成功才执行下一个
func executeInSequence<T, E: Error>(_ publishers: [AnyPublisher<T, E>]) -> AnyPublisher<T, E> {
    return publishers.dropFirst().reduce(into: publishers.first?.eraseToAnyPublisher()) { result, next in
        result = result?.flatMap { _ in next }.eraseToAnyPublisher()
    } ?? Empty().eraseToAnyPublisher()
}

// 扩展统一结果回调入口
extension Publisher where Output == Void, Failure == Error {
    func onResult(_ callback: @escaping (Result<Void, Error>) -> Void) -> AnyCancellable {
        return self.sink(
            receiveCompletion: { completion in
                if case .failure(let err) = completion {
                    callback(.failure(err))
                }
            },
            receiveValue: {
                callback(.success(()))
            }
        )
    }
}

调用示例

完全匹配你期望的调用形式,注意需要持有返回的AnyCancellable避免订阅提前释放:

var cancellable: AnyCancellable?
cancellable = executeInSequence([
    firstCall().eraseToAnyPublisher(),
    secondCall().eraseToAnyPublisher()
])
.onResult { finalResult in
    print(finalResult)
}

兼容原有签名的实现(不修改现有函数)

如果不需要调整原有Future<Result<Void, Error>, Never>的签名,可以直接用以下实现:

工具方法实现

import Combine

typealias AsyncCall = Future<Result<Void, Error>, Never>

func executeInSequence(_ calls: [AsyncCall]) -> AnyPublisher<Result<Void, Error>, Never> {
    return calls.dropFirst().reduce(into: calls.first?.eraseToAnyPublisher()) { result, next in
        result = result?.flatMap { prevResult -> AnyPublisher<Result<Void, Error>, Never> in
            // 前序调用失败直接返回错误,不执行后续任务
            if case .failure(let err) = prevResult {
                return Just(.failure(err)).eraseToAnyPublisher()
            }
            // 前序调用成功才执行下一个
            return next.eraseToAnyPublisher()
        }.eraseToAnyPublisher()
    } ?? Just(.success(())).eraseToAnyPublisher()
}

extension Publisher where Output == Result<Void, Error>, Failure == Never {
    func onResult(_ callback: @escaping (Result<Void, Error>) -> Void) -> AnyCancellable {
        return self.sink(receiveValue: callback)
    }
}

调用示例

和你给出的示例完全一致:

var cancellable: AnyCancellable?
cancellable = executeInSequence([firstCall(), secondCall()])
.onResult { finalResult in
    print(finalResult)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:27:03