我正在使用retry
和async
await
函数
def awaitRetry[T](times: Int)(block: => Future[T]): Future[T] = async {
var i = 0
var result: Try[T] = Failure(new RuntimeException("failure"))
while (result.isFailure && i < times) {
result = await { Try(block) } // can't compile
i += 1
}
result.get
}
Scala编译器报告错误。由于Try
没有应用方法需要Future[T]
。所以我使用隐式类
implicit class TryCompanionOps(val t: Try.type) extends AnyVal {
// can't use `apply`!
def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] =
f.map(value => Try(value))
}
// now we can convert Future[T] into Future[Try[T]] e.g,
await { Try.convertTriedFuture(block) }
我的问题是,
为什么我不能使用名称apply
而不是convertTriedFuture
?似乎scala编译器不允许重载仅隐式类中的apply
方法。
感谢。
答案 0 :(得分:2)
Scala开始寻找隐式转换,只有当它无法找到具有所需签名的现有方法时。但是在Try
随播广告对象中已有一个合适的方法:def apply[T](r: ⇒ T): Try[T]
,因此Scala会将T
中的apply
推断为Future[Something]
,并且不会检查隐式转化
此外,此实现不起作用:
def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] =
f.map(value => Try(value))
如果Future
失败,则不会调用map
的函数,并且await
会抛出异常,而async
会立即导致失败{ {1}}。因此,通过此实现,该函数实际上不会重试。
您需要以下内容:
Future
另外,我认为,在Futures上定义这种恢复方法可能更清晰:
def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] =
f.map(Success.apply).recover { case e => Failure(e) }
然后你可以拥有
implicit class FutureAdditionalOps[T](f: Future[T]) {
def recoverError: Future[Try[T]] =
f.map(Success.apply).recover { case e => Failure(e) }
}