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

Swift中对应Kotlin协程、等待异步任务完成的实现方案

问题原因

你原有代码的核心问题有两点:

  • 创建的两个Task是独立的非结构化任务,不会被checkData函数的执行生命周期绑定,函数不会等待两个任务执行完成就会直接退出
  • Swift的Task优先级只是给系统调度器的调度权重参考,不是强制的执行顺序保证,高优先级任务不会阻塞低优先级任务的调度执行,因此会出现低优先级任务先执行完成的情况
可实现「等待所有并发任务完成后再执行后续逻辑」的方案

Swift并发模型本身提供了和Kotlin协程对齐的结构化并发能力,完全可以实现等效的任务等待、调度能力,常用方案如下:

方案1:使用withTaskGroup/withThrowingTaskGroup(推荐,结构化并发实现)

这是和Kotlin协程coroutineScope { async {}.awaitAll() }完全等效的实现,属于结构化并发范畴:任务组的生命周期和当前作用域绑定,作用域退出前会自动等待所有组内任务执行完成,同时会自动传递取消信号,也支持配置任务优先级。
示例代码:

func checkData(firstName: String) async {
    // 进入任务组作用域
    await withTaskGroup(of: Void.self) { group in
        // 添加高优先级比对任务
        group.addTask(priority: .high) {
            await compareFirstName(firstName: firstName)
        }
        // 添加低优先级上传任务
        group.addTask(priority: .low) {
            await uploadFirstName(firstName: firstName)
        }
        // 无需手动写等待逻辑,作用域结束前会自动阻塞等待所有组内任务执行完毕
    }
    // 执行到此处时,两个任务已经全部完成,可以执行后续逻辑
    await yourFollowUpLogic()
}

注意:如果业务要求compareFirstName必须100%在uploadFirstName之前执行完成,不要使用并发调度,直接按顺序调用await即可,示例:

func checkData(firstName: String) async {
    // 严格顺序执行,前一个执行完成才会启动下一个
    await compareFirstName(firstName: firstName)
    await uploadFirstName(firstName: firstName)
    // 后续逻辑
    await yourFollowUpLogic()
}

如果任务可能抛出错误,把withTaskGroup替换为withThrowingTaskGroup即可,错误会自动向外抛出。

方案2:手动持有Task句柄调用value等待

如果需要更灵活的任务控制(比如单独取消某个任务),可以手动创建Task并持有引用,通过await task.value等待任务完成,等效于Kotlin协程的Job.join()/Deferred.await()。
示例代码:

func checkData(firstName: String) async {
    // 创建任务并持有句柄
    let compareTask = Task(priority: .high) {
        await compareFirstName(firstName: firstName)
    }
    let uploadTask = Task(priority: .low) {
        await uploadFirstName(firstName: firstName)
    }
    // 等待两个任务全部执行完成
    _ = await compareTask.value
    _ = await uploadTask.value
    // 执行后续逻辑
    await yourFollowUpLogic()
}

注意:该方案属于非结构化并发实现,不会自动传递取消信号,如果当前上下文被取消,需要手动调用cancel()方法取消两个子任务,非特殊场景优先使用方案1的任务组实现。

扩展:获取并发任务的返回值

如果需要像Kotlin协程的async一样拿到每个并发任务的返回结果,直接在任务组中遍历结果即可,还支持在某个任务失败时提前取消所有剩余任务:

func checkData(firstName: String) async -> Bool {
    let checkPassed = await withTaskGroup(of: Bool.self) { group in
        group.addTask(priority: .high) {
            await compareFirstName(firstName: firstName)
        }
        group.addTask(priority: .low) {
            // 上传任务返回是否上传成功
            return await uploadFirstName(firstName: firstName)
        }

        for await taskResult in group {
            if !taskResult {
                // 任意任务失败,取消所有剩余任务直接返回
                group.cancelAll()
                return false
            }
        }
        return true
    }
    return checkPassed
}

内容的提问来源于stack exchange,提问作者Steven-Carrot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:18:19