改成平行存取的方式之後,我們試看看存取a
、b
、c
裡面的內容:
get("/") {
val a = async { client.get<String>("http://127.0.0.1:8080/a") }
val b = async { client.get<String>("http://127.0.0.1:8080/b") }
val c = async { client.get<String>("http://127.0.0.1:8080/c") }
client.close()
call.respondText(a + b + c, contentType = ContentType.Text.Plain)
}
這時,我們會看到錯誤訊息:
Type mismatch.
Required: String
Found: Job
這是為什麼呢?這要說到 kotlin 的一個結構:coroutine。
coroutine,又叫做協程,是許多現代語言都有的一個結構。他可以透過控制線程來達成非同步的邏輯運作,在 ktor 裡面也是很重要的部分。
其中一個 coroutine 的使用方式,是使用 async
和 await
函式,來實作線程的暫停和啟動。
我們昨天使用 async
,來使程式運作到 val a = async { client.get<String>("http://127.0.0.1:8080/a") }
時,可以不用等資料回傳先往下運作。不過,我們並沒有等資料回傳,所以 a
取得的是 coroutine Job。
我們加上 await
,改寫成
get("/") {
val a = async { client.get<String>("http://127.0.0.1:8080/a") }
val b = async { client.get<String>("http://127.0.0.1:8080/b") }
val c = async { client.get<String>("http://127.0.0.1:8080/c") }
val result = a.await() + b.await() + c.await()
client.close()
call.respondText(result, contentType = ContentType.Text.Plain)
}
這樣,我們就可以等到 client.get
的資料了。