【问题标题】:How to handle a failed future in a for-comprehension如何在理解中处理失败的未来
【发布时间】:2020-12-28 19:55:11
【问题描述】:

我有以下理解。它应该删除我数据库中的一行,但前提是该行存在(因此,如果给定 id 有新闻):

override def deleteNews(newsId: Long): Int = {
    val getAndDelete = for {
         Some(news) <- newsDao.get(newsId)// returns Future[Option[News]]
         delete <- newsDao.remove(news)   // returns Future[Int]
     } yield delete
     Await.result(getAndDelete, responseTimeout)
}

但是当给定的 id 没有元素时,我不知道如何处理这种情况。目前抛出此异常:

Unexpected exception[NoSuchElementException: Future.filter predicate is not satisfied]

我希望我的方法不会太糟糕:D

我对 scala 比较陌生。

【问题讨论】:

  • 返回类型Int表示什么?
  • 受数据库查询影响的行
  • 应该返回 Future[Into] 并从那里编写,而不是等待

标签: scala future optional for-comprehension


【解决方案1】:

使用Await 并不是一个好主意:最好尽可能延迟阻塞。

IMO,给定 ID 的任何元素都不应该是失败的。 newsDao.get 应该返回 None 的成功未来,如果该 ID 没有任何内容,则不应在不存在的 ID 上调用 newsDao.remove,如果您可以提供帮助,则应该成功删除整体结果零行(因为我会查看deleteNews 的合同,以确保在调用和返回之间的某个时间点没有与newsId 相关的行(当然,在数据竞赛中有点手忙脚乱。 ..))。

因此,假设您无法更改 newsDao 的实现:

val getFut: Future[Option[News]] =
  newsDao.get(newsId).recover {
    // can still fail for other reasons
    case _: NoSuchElementException => None
  }

// I really prefer map/flatMap directly vs. for-comprehension sugar, especially when dealing with multiple monadicish things

// Not the most succinct, but leaving meaningful names in for documentation
val getAndRemove =
  getFut.flatMap { newsOpt =>
    newsOpt.map { news =>
      newsDao.remove(news)
    }.getOrElse(Future.successful(0))
  }

如果您仍然需要deleteNews 来返回一个裸露的Int,您可以Await.result 并接受您有时会抛出异常并且这可能不是最理想的。

【讨论】:

  • 是的,我承认,我不确定我是否能够在第一次尝试时将其转化为理解。
【解决方案2】:

正如 Levi 所说,始终尽量避免阻塞,并且当您进行模式匹配时,请确保处理所有情况。

您可以使用下面的 for-comprehension 来做到这一点:

def deleteNews(newsId: Long): Future[Option[Int]] =
  for {
    news   <- newsDao.get(newsId)
    delete <- Future.sequence(news.map(id => newsDao.remove(id)).toList)
  } yield delete.headOption

老实说,我没有使用这个技巧从Option[Future] 转到Future[Option]。我很想看看别人怎么说!

【讨论】:

    猜你喜欢
    • 2015-09-19
    • 2015-03-12
    • 1970-01-01
    • 2018-01-19
    • 2015-11-24
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多