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

Kotlin Async/Await:发送多GET请求并实时处理返回结果

如何在Kotlin协程中立即处理每个异步请求的返回结果?

我尝试向服务器发送多个GET请求,希望在每个请求的结果返回时立即进行处理,但当前代码是按顺序等待所有请求完成后再处理结果。相关代码和控制台输出如下:

原代码

suspend fun getRequests(value: Int): Int {
    val rnd = (100..3000L).random()
    println("Delay for $rnd") // simulate network time delay.
    delay(rnd)
    return value * 2
}

fun main() {
    runBlocking {
        launch(Dispatchers.IO) {
            val myList: ArrayList<Deferred<Int>> = ArrayList()
            for (i in 1..10) {
                println("GET request sent: no$i")
                myList.add(async { getRequests(i) })
            }
            myList.forEach { println(it.await()) } // process the results
        }
    }
}

原控制台输出

GET request sent: no1
GET request sent: no2
GET request sent: no3
GET request sent: no4
GET request sent: no5
GET request sent: no6
GET request sent: no7
Delay for 706
Delay for 487
Delay for 2894
Delay for 1857
Delay for 353
GET request sent: no8
Delay for 2216
GET request sent: no9
Delay for 546
GET request sent: no10
Delay for 1806
Delay for 1291
Delay for 2830
2
4
6
8
10
12
14
16
18
20

问题原因分析

你现在的写法之所以会按顺序输出结果,是因为你先把所有Deferred对象收集到列表中,然后按列表顺序逐个调用await()。哪怕某个请求已经提前完成,也得等列表中排在它前面的Deferred.await()执行完毕,才会处理它的结果——这就导致所有结果要等全部请求都完成后,才按原请求的顺序输出,而不是完成即处理。


解决方案:为每个请求单独启动结果处理协程

要实现“结果一返回就立即处理”,你需要在每个异步请求启动后,立刻为它的结果处理单独开一个协程,而不是等到所有请求都启动完再统一处理。

修改后的代码示例1(保留async)

suspend fun getRequests(value: Int): Int {
    val rnd = (100..3000L).random()
    println("Delay for $rnd") // simulate network time delay.
    delay(rnd)
    return value * 2
}

fun main() {
    runBlocking {
        launch(Dispatchers.IO) {
            for (i in 1..10) {
                println("GET request sent: no$i")
                // 每个async启动后,立即启动协程等待结果并处理
                launch {
                    val result = async { getRequests(i) }.await()
                    println("Processed result: $result")
                }
            }
        }
    }
}

修改后的代码示例2(更简洁,无需async)

如果不需要保留对异步任务的Deferred引用,直接在launch里调用suspend函数即可:

fun main() {
    runBlocking {
        launch(Dispatchers.IO) {
            repeat(10) { idx ->
                val requestNum = idx + 1
                println("GET request sent: no$requestNum")
                launch {
                    val result = getRequests(requestNum)
                    println("Processed result: $result")
                }
            }
        }
    }
}

预期输出效果

结果会按请求完成的先后顺序输出,比如:

GET request sent: no1
GET request sent: no2
GET request sent: no3
GET request sent: no4
GET request sent: no5
Delay for 353  // no5的延迟最短
GET request sent: no6
...
Processed result: 10  // no5的结果最先被处理
Processed result: 4   // no2的结果随后处理
Processed result: 18  // no9的结果接着处理
... 后续结果按完成顺序输出

进阶:等待所有任务处理完成

如果你需要在所有请求的结果都处理完后执行后续操作,可以收集每个处理协程的Job,最后调用joinAll():

fun main() {
    runBlocking {
        launch(Dispatchers.IO) {
            val processingJobs = mutableListOf<Job>()
            
            for (i in 1..10) {
                println("GET request sent: no$i")
                val job = launch {
                    val result = getRequests(i)
                    println("Processed result: $result")
                }
                processingJobs.add(job)
            }
            
            processingJobs.joinAll() // 等待所有结果处理完成
            println("All requests have been processed successfully!")
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 16:07:28