Scala新手求助:含迭代器与状态检查的While循环优化问题
Hey there! Since you're new to Scala and need a flexible way to wait for a condition (like your record completion check) with a timeout, let's refactor your Iterator-based approach to accept the check logic as a parameter. This way you can reuse the same waiting logic for any scenario.
The Core Idea: Higher-Order Functions
Scala shines with higher-order functions—functions that take other functions as parameters. We'll create a reusable wait function that accepts your checkIfRecordIsComplete (or any similar check) as an argument.
Step 1: Implement the Generic Wait Function
Here's a clean, reusable implementation that matches your requirements (max 15s wait, 1s interval between checks):
def waitUntilConditionMet( maxWaitSeconds: Int = 15, checkIntervalSeconds: Int = 1 )(checkCondition: => Boolean): Boolean = { // Create an infinite iterator that checks the condition each time Iterator.continually { if (checkCondition) { true // Condition met, signal we're done } else { Thread.sleep(checkIntervalSeconds * 1000) // Wait 1s before next check false // Condition not met yet } } // Limit to maxWaitSeconds iterations (one per second) .take(maxWaitSeconds) // Stop as soon as we get a "true" (condition met) .exists(identity) }
Let's break this down:
maxWaitSeconds: Int = 15: Defaults to your 15s timeout (you can override it for other scenarios)checkIntervalSeconds: Int = 1: Defaults to 1s between checks (easily adjustable)checkCondition: => Boolean: This is your parameterized check logic. The=>makes it a call-by-name parameter, meaning it runs fresh every time we check (perfect for dynamic conditions like record completion)Iterator.continually: Generates an infinite sequence of checkstake(maxWaitSeconds): Ensures we don't wait longer than the timeoutexists(identity): Stops iterating immediately when the check returnstrue(no unnecessary waiting once the condition is met)
Step 2: Use It With Your Record Completion Check
Now you can pass your existing checkIfRecordIsComplete method directly to this function:
// Example of your existing check method def checkIfRecordIsComplete: Boolean = { // Replace this with your actual logic (e.g., query DB, check file status) println("Checking record completion status...") // Simulate real-world behavior (e.g., condition is met after ~7s) System.currentTimeMillis() % 10000 > 7000 } // Call the generic wait function val recordCompleted = waitUntilConditionMet()(checkIfRecordIsComplete) // Handle the result if (recordCompleted) { println("Success! Record completed within the timeout window.") } else { println("Timeout: Record didn't complete within 15 seconds.") }
Bonus: Asynchronous Alternative (Optional)
If you don't want to block the main thread (e.g., in a web app), you can wrap this in a Future for non-blocking waiting:
import scala.concurrent.{Await, Future} import scala.concurrent.duration._ import scala.concurrent.ExecutionContext.Implicits.global def waitUntilConditionMetAsync( maxWaitSeconds: Int = 15, checkIntervalSeconds: Int = 1 )(checkCondition: => Boolean): Boolean = { val waitFuture = Future { Iterator.continually { if (checkCondition) true else { Thread.sleep(checkIntervalSeconds * 1000) false } }.take(maxWaitSeconds).exists(identity) } // Wait for the future to complete, with a tiny buffer over the timeout Await.result(waitFuture, maxWaitSeconds.seconds + 1.second) } // Usage is almost identical val asyncResult = waitUntilConditionMetAsync()(checkIfRecordIsComplete)
This version keeps your main thread free while waiting, which is useful in concurrent applications.
内容的提问来源于stack exchange,提问作者WDrgn

