以下代码尝试使用Reactivemongo通过ID获取文档。但是,我不知道如何处理ID错误时抛出的IllegalArgumentException!
试过下面的代码,但编译器对case _ => Future.successful(None)
不满意,它说:found scala.concurrent.Future[None.type] required Option[SomeModel]
。还尝试case _ => None
但没有成功。
def getById(id: String)(implicit ec: ExecutionContext): Future[Option[SomeModel]]={
this.get( BSONDocument("_id" -> BSONObjectID(id)) ).map {
res => Future.successful(res)
}.recover {
case _ => Future.successful(None)
}
}
def get(query: BSONDocument)(implicit ec: ExecutionContext): Future[Option[SomeModel]]= {
collection.find(query).one[SomeModel](ReadPreference.Primary)
}
答案 0 :(得分:1)
您感到困惑recover
和recoverWith
。
这两个函数都期望PartialFunction
接受Throwable
并且两个函数都返回Future[U]
,但
recover
的{{1}}应返回PartialFunction
U
应返回recoverWith
。在您的情况下,您可以使用Future[U]
:
recover
更新:您可以修改get(BSONDocument("_id" -> BSONObjectID(id)))
.recover { case _ => None }
// you don't need map(res => Future.successful(res)
以返回失败的get
,而不是投放Future
。可能的方法是使用IllegalArgumentException
及其Try
:
recover
更新
当我做的时候它起作用了
import scala.util.Try
def get(query: BSONDocument)(implicit ec: ExecutionContext): Future[Option[SomeModel]] =
Try(collection.find(query).one[SomeModel](ReadPreference.Primary))
.recover{ case t => Future.failed(t) }.get
答案 1 :(得分:1)
我理解你的问题,
...我不知道如何处理ID错误时抛出的IllegalArgumentException!
我认为,更好的解决方案是
def getById(id: String)(implicit ec: ExecutionContext): Future[Option[SomeModel]]={
//Try to parse bson id from string. This method return Try[BSONObjectId] and we can simple `match` them
BSONObjectId.parse(id) match {
// valid bson id
case Success(bsonId) => this.get( BSONDocument("_id" -> bsonId) )
//We catch IllegalArgumentException and just return None
case Failure(ex) => Future[Option[SomeModel]](None)
}
}
在你的代码中,Scala尝试在调用get
方法之前从字符串解析BSONObjectId,如果字符串id无效,则BSON在当前线程中抛出异常(不在方法{{1}的Future
结果中}})。这就是get
无法执行的原因。方法recover {case _ => Future.successful(None)}
和recover
仅在recoverWith
存储某些异常时执行。例如,此代码也可以使用:
Future
但是此变体很复杂(再创建一个def getById(id: String)(implicit ec: ExecutionContext): Future[Option[SomeModel]]={
//create Future, that will be store exception (if id is invalid) or valid BSON id.
//method flatMap because this.get return Future type.
Future(BSONObjectId(id)).flatMap{ bsonId =>
//this executes only if string id is valid bson.
this.get( BSONDocument("_id" -> bsonId) )
}.recover{
//this will be execute only if string id is invalid bson.
// the best practice to catch non-fatal Throwables via class scala.util.control.NonFatal
case NonFatal(e) => None
}
}
,Future
,使用flatMap
控件进行恢复。我更倾向于使用NonFatal
方法的第一个变体(如果没有额外的期货和控制,它会变得更容易)。