当前位置: 首页 > 知识库问答 >
问题:

Scala future的理解失败

令狐嘉禧
2023-03-14

我有三个连续的未来,并在理解中使用

val comF = for {
  f1 <- future1
  f2 <- future2
  f3 <- future3
} yield {
  // something
}

comF onSuccess { }
comF onFailure { 
  // ----------------      Here is the problem  --------------------------------
  //
  // How do I know which future failed(throw exception), when the callback comes here ?
  // Thanks for the help! Different futures using different exceptions can solve it.
}

现在我有一个像List[Future[T]这样的未来列表,首先我使用这种方法将其转移到Future[List[T]](为什么这个未来列表到未来列表的转换编译和工作?)。然后我得到未来

val fList: Future[List[T]]
fList on Failure {
  // 
  // How do I know which is Fail now >??
}

共有3个答案

孙胜泫
2023-03-14

这位受人尊敬的@Rit(Brendan McAdams)终于说服我在他的演讲《怀疑论者看斯卡拉兹的“Gateway Drugs”》中用脱节来尝试斯卡拉兹。您的代码将被包装在析取中,如下所示:

val comF = for {
  f1 <- future1 \/> "Future 1 failed"
  f2 <- future2 \/> "Future 2 failed"
  f3 <- future3 \/> "Future 3 failed"
} yield {
  // something
}

相关问题

左丘成天
2023-03-14

您使用的是< code>flatMap,因此期货嵌套在一个期货中。

你的代码是

import scala.concurrent.Future

val future1, future2, future3 = Future[Any]()

val comF = for {
  f1 <- future1
  f2 <- future2
  f3 <- future3
} yield {
  // something
}

comF onSuccess { ??? }
comF onFailure { ??? }

当我将脱糖规则应用于您的理解时,我得到

val comF = (future1).flatMap { case f1 => 
  (future2).flatMap { case f2 => 
    (future3).map { case f3 => {
        // something
      }
    }
  }
}

您可以在此处清楚地看到flatMap的使用。原则上,flatMap做了两件事:它将一个函数应用于第一个Future的结果。这必须是一个函数,它将第一个 Future 的结果映射到另一个 Future,即嵌套在第一个 Future 中的未来(这是映射部分)。然后,它“取消”两个期货,并将它们合并为一个单一的未来平面部分)。在这一点上,这两种期货不再存在(从概念的角度来看;从技术上讲,它们仍然存在)。相反,只有一个“合并”的未来

对< code>flatMap的两次调用在原来的三次调用的基础上创建了一个新的< code>Future。这就是为什么你不能发现,三个原始的< code >期货中的哪一个引发了异常:不是它们中的任何一个。相反,新创建的< code>Future运行并引发异常。

如果您想知道在引发异常之前运行了计算的哪些步骤,您必须单独跟踪进度,例如通过Exception中的附加参数。或者,您可以删除(平面图)并一个接一个地运行单个Futures

首先,我们创建一个新的异常类,其中包含真正的异常以及一些信息,异常来自何处

class ExceptionWithOrigin[T](val origin : T, nested : Throwable) extends Exception(nested)

object ExceptionWithOrigin {
  def wrapFuture[T,U](origin : T, f : Future[U]) : Future[U] = {
    f.transform(Predef.identity, new ExceptionWithOrigin[T](origin,_))
  }

  def wrapFuture[U](f : Future[U]) = wrapFuture(f,f)
}

对于Futures我们没有特殊要求。

val future1,future2,future3 = Future[Any]()

然后,我们使用新创建的异常类的伴随对象中的帮助器方法包装给定的 Futures

import ExceptionWithOrigin._

val comF = for {
  result1 <- wrapFuture(future1)
  result2 <- wrapFuture(future2)
  result3 <- wrapFuture(future3)
} yield {
  // something
}

当您发现一些异常ex时,您现在只需使用ex.origin来找出它来自哪里。当然,起源并不完全正确。原来的 Futures future1future2future3 并没有真正执行。取而代之的是,由 flatMap 创建的新创建的未来运行。但尽管如此,起源仍然有效。

顺便说一下,您应该将< code>f1 、< code>f2和< code>f3重命名为< code >结果1 、< code >结果2和< code >结果3。它们不代表一个< code>Future,而是每个< code>Future的计算结果(每个< code>Future返回的值)。

韦繁
2023-03-14

考虑代码:

def func = {
  try {
    val x = maybeThrows
    val y = maybeThrowsToo
    val z = maybeThrowsAsWell
    result(x, y, x)
  } catch (RuntimeException e) {
    // How do I know which maybeThrows failed?
  }
}

未来案例的工作原理基本相同。

即使在<code>列表</code>中分组计算也没有帮助:

def func = {
  try {
    val x = maybeThrows
    val y = maybeThrowsToo
    val z = maybeThrowsAsWell
    val list = List(x, y, z)
    result(list)
  } catch (RuntimeException e) {
    // How do I know which maybeThrows failed?
  }
}

扰流器:你必须明确追踪哪一次计算失败。如果使用try/catch完成,将产生一些样板文件。但幸运的是,有了未来(以及尝试),样板文件并没有那么糟糕:

class TaggedException(val idx, exc: Exception)

def tagFailedWithIndex[T](idx: Int, f: Future[T]): Future[T] = 
  future recoverWith { case exc => Future.failed(new TaggedException(idx, exc)) }

val comF = for {
  f1 <- tagFailedWithIndex(0, future1)
  f2 <- tagFailedWithIndex(1, future2)
  f3 <- tagFailedWithIndex(2, future3)
} yield something(f1, f2, f3)

comF onFailure { 
  case exc: TaggedException => "%d computation failed".format(exc.idx)
}

剧透你必须跟踪哪些计算明确失败。如果使用try/catch完成,它将导致很多样板。但幸运的是,有TryFuture的行为更加相同:

class TaggedException(val idx, exc: Exception)

def tagFailedWithIndex[T](idx: Int, f: Future[T]): Future[T] = 
  future recoverWith { case exc => Future.failed(new TaggedException(idx, exc)) }

val comF = for {
  f1 <- tagFailedWithIndex(0, future1)
  f2 <- tagFailedWithIndex(1, future2)
  f3 <- tagFailedWithIndex(2, future3)
} yield something(f1, f2, f3)

comF onFailure { 
  case exc: TaggedException => "%d computation failed".format(exc.idx)
}
 类似资料:
  • 本文向大家介绍svn 清理失败 (cleanup 失败) 的快速解决方法,包括了svn 清理失败 (cleanup 失败) 的快速解决方法的使用技巧和注意事项,需要的朋友参考一下 1、cmd指令,进入.svn目录,找到wc.db文件 sqlite 3 打开 2、 对 svn源代码目录 右键, clean up, 稍等1至5分钟左右,然后会提示 清理成功 以上就是小编为大家带来的svn 清理失败 (

  • 注: 内容翻译自 Understand failures 在机器的大量部署中失败是很常见的。当硬件或者软件故障时单台机器失败。当电力故障或者网络问题时多台机器一起失败。多种失败也可能一起发生;几乎不可能列举出所有可能的失败场景。 在这节中,我们分类失败的种类并讨论 etcd 是如何设计来容忍这些失败的。大部分用户,不是所有,可以映射一个特别的失败到一种失败。为了应对罕见或者 不可恢复的失败, 总是

  • 我正在使用从2个Kafka主题中消费,每个主题都有6个分区。喷口进入单个螺栓以解压缩相关字节,然后进入第二个螺栓以进一步处理。 当我看到storm-ui的时候,这些数字没有多大意义,我希望有人能给我一些启示。 > Kafka的口水说它“收集”了3600个元组,失败了73M个元组。再看下一组的螺栓,我看到有的已经顶起了73米,有的已经顶起了1.3米(没有出现故障),而有的已经顶起了1.3米(没有出现

  • 我试图了解CTC损失是如何为语音识别工作的,以及它如何在Keras中实现。 我认为我理解的(如果我错了,请纠正我!) 大体上,CTC损耗被添加到经典网络之上,以便逐个元素(文本或语音的字母)解码顺序信息,而不是直接解码元素块(例如单词)。 假设我们将一些句子的语句作为MFCC输入。 使用CTC损失的目标是学习如何使每个字母在每个时间步与MFCC匹配。因此,Dense softmax输出层由与句子组

  • 我正在进行一个在线课程,其中一个问题要求我们根据列表中的索引将名称与基于以下列表和字典的关键字的理解中的工资相匹配: 期望输出: 我写了以下内容: 返回一个空集。 有人能给我一两个提示(不是代码答案)如何解决这个问题吗? 谢谢

  • 我在spark streaming应用程序中看到一些失败的批处理,原因是与内存相关的问题,如 无法计算拆分,找不到块输入-0-1464774108087