在for-comprehension中撤消/补偿服务调用

时间:2018-05-28 10:45:06

标签: scala

我有几个服务电话要求(1 GET和5个POST)。如果1 POST工作并且下一个问题发生,我想补偿/回滚/撤消第一个POST

因此,在下文中,如果func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CellRID") as! VideoAdsCell let youtubeId = extractYoutubeIdFromLink(link: arrayVideo[indexPath.row].video) if let url = URL(string: "http://img.youtube.com/vi/\(youtubeId!)/1.jpg") { print(url) UIImage.downloadFromRemoteURL(url, completion: { thumbnail,error in guard let thumbnail = thumbnail, error == nil else { print(error) return } cell.imageForMain.image = thumbnail cell.viewForMain.layer.masksToBounds = false cell.viewForMain.layer.shadowOffset = CGSize(width: -1, height: 1) cell.viewForMain.layer.shadowRadius = 1 cell.viewForMain.layer.shadowOpacity = 1 cell.viewForMain.layer.cornerRadius = 8 } } return cell } 成功,我需要致电deleteFoo,但insertFooinsertChild1

中出现任何问题
insertChild4

我一直试图将其分解为两个以进行理解,但每次我最终都会遇到杂乱无味的代码(但是在编辑之后它现在有效,但我对这种风格并不满意)

for {
    barName <- barName()
    f <- insertFoo(barName)
    _ <- insertChild1(f.id) if f.id.isDefined
    _ <- insertChild2(f.id) if f.id.isDefined
    _ <- insertChild3(f.id) if f.id.isDefined
    _ <- insertChild4(f.id) if f.id.isDefined
} yield f

P.S。也许猫有些东西(我们已经在这里和那里使用猫)

1 个答案:

答案 0 :(得分:2)

您可以使用类型来表示操作的结果。以下for-comprehension将产生Future[Either[Exception, Foo]],它将是以下之一:

  • 如果插入foo失败
  • ,将来会失败
  • 一个成功的Future[Left[Exception]],它将包含导致插入子节点失败的异常
    • 此案例还会处理删除foo
  • 成功Future[Right[Foo]]
for {
  barName <- barName()
  f <- insertFoo(barName) if f.id.isDefined
  res <- insertChildren(f).recoverWith(cleanUpFoo(f.id))
} yield res

private def insertChildren(f: Foo): Future[Either[Exception, Foo]] =
  for {
    _ <- insertChild1(f.id)
    _ <- insertChild2(f.id)
    _ <- insertChild3(f.id)
    _ <- insertChild4(f.id)
  } yield Right(f)

private def cleanUpFoo(id: Int)(e: Exception): Future[Either[Exception, Foo]] =
  deleteFoo(id).map(_ => Left(e))