withTimeout และ withTimeoutOrNull
จำกัดเวลาการทำงานด้วยตัวห่อ timeout และจัดการ TimeoutCancellationException
withTimeout และ withTimeoutOrNull เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
เหตุใดจึงต้องกำหนดเวลาสิ้นสุด
โคโรทีนอาจค้างอยู่ไม่สิ้นสุดระหว่างทำงานกับเครือข่ายหรือการรับส่งข้อมูลเข้าออก withTimeout จะยกเลิกบล็อกหากบล็อกทำงานไม่เสร็จภายในจำนวนมิลลิวินาทีที่กำหนด
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
withTimeout(200) {
delay(1000) // simulates slow network
println("This never prints")
}
} catch (e: TimeoutCancellationException) {
println("Timed out!")
}
}พื้นฐานของ withTimeout
withTimeout(millis) { ... } จะโยน TimeoutCancellationException (คลาสย่อยของ CancellationException) หากบล็อกทำงานเกินขีดจำกัด
import kotlinx.coroutines.*
suspend fun fetchData(): String {
delay(100)
return "data"
}
fun main() = runBlocking {
val result = withTimeout(500) {
fetchData()
}
println(result) // data
}withTimeoutOrNull
withTimeoutOrNull จะคืนค่า null เมื่อหมดเวลาแทนการโยนข้อยกเว้น ทำให้จัดการการหมดเวลาในฐานะลำดับการทำงานปกติได้ง่ายขึ้น
import kotlinx.coroutines.*
fun main() = runBlocking {
val result: String? = withTimeoutOrNull(200) {
delay(1000)
"done"
}
println(result ?: "Timeout — using default")
}การหมดเวลาพร้อมค่าที่ส่งคืน
ฟังก์ชันทั้งสองจะคืนค่าของนิพจน์สุดท้ายในบล็อกเมื่อทำงานสำเร็จ
import kotlinx.coroutines.*
fun main() = runBlocking {
val response = withTimeoutOrNull(500) {
delay(100)
mapOf("status" to 200, "body" to "OK")
}
println(response?.get("status")) // 200
}การซ้อนการกำหนดเวลาสิ้นสุด
การกำหนดเวลาสิ้นสุดภายในจะหมดเวลาก่อน ส่วนการกำหนดเวลาสิ้นสุดภายนอกจะทำงานก็ต่อเมื่อส่วนภายในยังไม่ยกเลิกก่อน ซึ่งมีประโยชน์สำหรับการกำหนดเวลาสิ้นสุดต่อคำขอเทียบกับการกำหนดเวลาสิ้นสุดโดยรวม
import kotlinx.coroutines.*
fun main() = runBlocking {
withTimeoutOrNull(1000) { // global
withTimeoutOrNull(200) { // per-call
delay(300)
println("inner done") // won't print
} ?: println("Inner timed out")
delay(100)
println("outer still running")
}
}TimeoutCancellationException
TimeoutCancellationException เป็น CancellationException ดังนั้นกลไกของโคโรทีนจึงถือว่าเป็นการยกเลิกตามปกติ และจะไม่ส่งต่อไปยังขอบเขตแม่
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
withTimeout(100) { delay(1000) }
} catch (e: TimeoutCancellationException) {
println("Caught in child: ${e.message}")
}
}
job.join()
println("Parent still running: ${isActive}")
}การล้างทรัพยากรเมื่อหมดเวลา
ใช้ finally ภายใน withTimeout เพื่อคืนทรัพยากร แม้เวลาจะหมดลงแล้ว
import kotlinx.coroutines.*
fun main() = runBlocking {
val result = withTimeoutOrNull(150) {
try {
println("Opening resource")
delay(300)
"result"
} finally {
println("Closing resource") // always runs
}
}
println("Result: $result")
}การลองใหม่พร้อมการกำหนดเวลาสิ้นสุด
ผสานการกำหนดเวลาสิ้นสุดเข้ากับตรรกะการลองใหม่: ดำเนินการหนึ่งครั้งภายในเวลาสิ้นสุดต่อครั้ง แล้วลองใหม่เมื่อผลลัพธ์เป็น null
import kotlinx.coroutines.*
suspend fun tryFetch(attempt: Int): String? = withTimeoutOrNull(200) {
delay(if (attempt < 3) 300L else 100L) // fails first 2 attempts
"success on attempt $attempt"
}
fun main() = runBlocking {
var result: String? = null
var attempt = 1
while (result == null) {
result = tryFetch(attempt++)
}
println(result)
}withTimeout ใน ViewModel
ใน ViewModel ของแอนดรอยด์ ให้ครอบการเรียกคลังข้อมูลด้วย withTimeoutOrNull ภายใน viewModelScope.launch เพื่อแสดงสถานะข้อผิดพลาดเมื่อการตอบสนองล่าช้า
import kotlinx.coroutines.*
// Pseudocode pattern:
suspend fun loadUser(): String = withTimeoutOrNull(3000) {
// repo.getUser()
delay(100)
"Alice"
} ?: "Timeout — using cached data"
fun main() = runBlocking { println(loadUser()) }ข้อควรระวังด้านความแม่นยำ
withTimeout อาศัยตัวจัดส่งโคโรทีน ในการทดสอบที่ใช้ TestCoroutineScheduler เวลาเป็นเวลาเสมือนและสามารถเลื่อนไปข้างหน้าด้วยตนเองได้
import kotlinx.coroutines.*
// In unit tests with runTest:
// runTest {
// withTimeout(1000) {
// delay(999) // virtual time — completes instantly
// println("done")
// }
// }
fun main() = runBlocking {
println("Use runTest for virtual-time timeout testing")
}การเลือกระหว่างสองแบบ
ใช้ withTimeout เมื่อการหมดเวลาถือเป็นข้อผิดพลาด ใช้ withTimeoutOrNull เมื่อการหมดเวลาเป็นผลลัพธ์ที่คาดหมายได้ (เช่น ไม่พบข้อมูลในแคช หรือการโหลดข้อมูลล่วงหน้าแบบไม่บังคับ)
import kotlinx.coroutines.*
fun main() = runBlocking {
// Mandatory: throw on timeout
// withTimeout(500) { criticalOp() }
// Optional: null on timeout
val cached = withTimeoutOrNull(50) {
delay(200); "fresh"
} ?: "stale"
println(cached)
}ตรวจสอบอย่างรวดเร็ว
withTimeoutOrNull จะคืนค่าอะไรเมื่อบล็อกทำงานเกินขีดจำกัดเวลา
ทบทวน
withTimeout จะโยนข้อยกเว้นเมื่อหมดเวลา ส่วน withTimeoutOrNull จะคืนค่า null ทั้งสองแบบยกเลิกบล็อกด้วยวิธีร่วมมือกันและเรียกใช้บล็อก finally ใช้ finally สำหรับล้างทรัพยากร และใช้ withTimeoutOrNull เมื่อการหมดเวลาเป็นผลลัพธ์ที่คาดหมายได้
เรียนรู้ Kotlin ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 51
- บทเรียน
- 203
คำถามที่พบบ่อย
บทเรียน “withTimeout และ withTimeoutOrNull” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “withTimeout และ withTimeoutOrNull” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “withTimeout และ withTimeoutOrNull”
จำกัดเวลาการทำงานด้วยตัวห่อ timeout และจัดการ TimeoutCancellationException คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “withTimeout และ withTimeoutOrNull” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม
ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การยกเลิกร่วมมือกัน: isActive และ ensureActive
- withTimeout และ withTimeoutOrNull
- การเก็บกวาดด้วย finally และ NonCancellable
- การส่งต่อการยกเลิกในลำดับชั้น Coroutine