Something like this is possible:
object PimpMyFuture { implicit class PimpedFuture[T](val f: Future[T]) extends AnyVal { def after(delay: FiniteDuration)(callback: => Unit): Future[T] = { Future { blocking { Await.ready(f, delay) } } recover { case _: TimeoutException => callback } f } } } import PimpMyFuture._ Future { Thread.sleep(10000); println ("Done") } .after(5.seconds) { println("Still going") }
This implementation is simple, but it basically doubles the number of threads you need - each active future effectively takes up two threads, which is a bit wasteful. In addition, you can use scheduled tasks so that your expectations are not blocked. I do not know the "standard" scheduler in scala (each lib has its own), but for a simple task like this, you can directly use java TimerTask :
object PimpMyFutureNonBlocking { val timer = new java.util.Timer implicit class PimpedFuture[T](val f: Future[T]) extends AnyVal { def after(delay: FiniteDuration)(callback: => Unit): Future[T] = { val task = new java.util.TimerTask { def run() { if(!f.isCompleted) callback } } timer.schedule(task, delay.toMillis) f.onComplete { _ => task.cancel } f } } }
source share