我希望下面的代码在其中一个方法<code>callfuture1()</code>或<code>callfuture2()</code>抛出异常时返回自定义消息。我的理解是,如果任何一个未来失败,f
都将是失败的未来。
但是,当 callfuture1
引发异常时。f.onFailure
不执行。相反,我看到调用堆栈停止在 callFuture1()
中的代码行,其中发生了异常并返回了标准内部错误。为什么会这样?
val f = for {
x <- callfuture1()
y <- callfuture2()
} yield y
f.onFailure {
//send an internalserver error with some custom message
}
f.map {
//send data back
}
====更新====
我从响应中看到,潜在的问题是异常被抛出未来,因此我的代码无法捕获失败的未来。所以我改变了代码,使得异常只发生在将来。我仍然无法解释我所看到的行为。(我想知道它是否与Play框架有任何关系。
def controllerfunction(id: String) = Action.async{
val f = for{
x <- callfuture1(id)
y <- callfuture2(x)
} yield y
y.onFailure{case t =>
println("This gets printed");
Ok("shit happened, but i am still ok")}
y.map{resp:String => Ok(resp)}
}
def callfuture1(id: String):Future[Obj1] = {
for {
val1 <- callfuture1.1(id)
val2 <- callfuture1.2(val1)
} yield val2
}
def callfuture1.2:Future[Obj3] = Future{
thrown new Exception("TEST ME");
}
def callfuture 1.1:Future[Obj4] = {...}
def callfuture2: Future[String] = {....}
期待。方法callfuture1.2在未来抛出一个异常,所以我的期望是onFailure应该被执行,(它确实被执行了),返回的响应应该是“Shit happened,但我仍然没事”
实际情况 Play框架返回 InternalServerError,我在控制台上看到错误堆栈。我看到 printlin(“This get print”) 正在执行。
无法理解发生了什么。有什么见解吗?
====更新2=====
我验证了只有在play框架的控制器内部调用时才会发生此问题(我正在使用play 2.5)。作为一个独立的 scala 程序,一切按预期工作。我相信播放错误处理会捕获未处理的异常并打印堆栈跟踪。我认为这应该只发生在开发环境中。
似乎在< code>callfuture1()中,您没有像
def callfuture1(): Future[?] = Future {
val x = ...
x
}
但你的代码似乎是
def callfuture1(): Future[?] = {
val x = ... // some error happen here
Future(x)
}
因为它在未来之外,所以你的错误会直接出现在你的程序代码中
如果call Future1
抛出“未来之外”,就会发生这种情况。您的理解被分解为:
val f = callfuture1.flatMap{ x =>
callfuture2.map{ y =>
y
}
}
如果<code>callfuture2</code>立即抛出(与返回失败的未来相反),您仍将以失败的未来告终,因为<code>callfuture2</code>在<code>future内部调用。flatMap,它捕获异常并将其转化为失败的未来(与<code>Future.map</code>相同)。
call Future1
的情况不同:如果它立即抛出,则没有封闭的Future.map
或Future.flatMap
将其变成失败的未来。
一般来说,您应该尽量避免使用返回Future
并且也可以抛出错误的方法。这意味着如果call Future1
执行任何可以抛出的操作,它应该会捕获它并在您随后返回的失败未来中打开异常。
更新:关于你的更新,关于你如何期望“狗屎发生了,但我仍然很好”被返回:
正如马頔在评论中暗示的那样,< code>Future.onFailure只能用于副作用。未来是不可变的。如果你想从一个失败的异常中恢复,没有办法修改原来的(失败的)未来,你实际上能做的就是把它转换成一个新的未来。看看< code>Future.recover。它做的正是你所需要的,即它允许通过匹配失败的结果(如果有的话)并将其转换为成功的未来来转换输入的未来。这相当于一个捕捉条款,但对期货来说。具体来说,你真正想做的是这样的:
def controllerfunction(id: String) = Action.async{
val f = for{
x <- callfuture1(id)
y <- callfuture2(x)
} yield y
f.map{ resp: String =>
Ok(resp)
}.recover{
case t: Throwable =>
println("This gets printed");
Ok("shit happened, but i am still ok")
}
}
给定的带有Selenium的Robot框架已准备好在Chrome中执行测试它工作了很长时间当我现在用Jenkins在Robot框架中执行测试时,我收到一个错误“02:05:44 WebDriverException:消息:未知错误:无法处理扩展#1 02:05:44from未知错误:CRX验证失败:3” 升级后的Chrome和驱动程序可能无法使用旧的插件吗?我该怎么解决这个问题?升级插件?升级驱动
在Scala中,未来可能会失败,这可以异步发现: 你将如何“翻译”成Clojure?我的阅读让我相信Clojure未来/promise模型没有Scala的强大,你不能就这样抓住失败。那么该怎么办呢? Scala的未来永远不需要被问到它的价值——当它好并准备好时,它会告诉你发生了什么(包括它是否失败——这是这个问题的关键)。这就是我所说的“异步”的意思。Scala的未来可以处于三种可能的状态之一——
异常严重:Servlet。路径为[z2]的上下文中servlet[dispatcher]的service()引发异常[请求处理失败;嵌套异常为org.springframework.dao.DataIntegrityViolationException:not null属性引用null或瞬时值:com.spring.entity.Product.cd;嵌套异常为org.hibernate.Prop
当我尝试连接到Oracle数据库时,出现了以下问题。 有例外 此reportMapper.xml
问题内容: 我正在开发一个Android应用,该应用必须将json格式的Java对象保存到SQLite数据库中。我为此操作编写了代码,然后他们必须提取Json对象并将其重新转换为Java对象。当我尝试调用将json对象反序列化为字符串的方法时,我在Android Studio中发现此错误: 当我尝试捕获程序运行但不反序列化json对象时。 这是该方法的代码: 你能帮我吗? 问题答案: 是的,您需要
问题内容: 当我运行程序时,出现此错误: 未处理无效的强制转换异常 这是用于填充数据库的表单的一部分,而Visual Studio会将int cast标记为错误 问题答案: 我 强烈 怀疑,您用错误的方式参数化了您的零件。您至少需要弄清楚您试图获取包含那些字符串的值。喜欢; 不要使用尽可能多的东西。有时它 可能会 产生意外和令人惊讶的结果 。使用方法重载来指定参数类型及其大小。 也可以使用语句自动