尝试失败不会捕获异常

时间:2018-03-05 14:11:20

标签: scala

在下面的代码中,我有两个Play for Scala函数,第一个捕获异常(这很好),而在第二个我尝试使用Try重写它。

Try我遇到两个问题:(1)当数字为负数时,方法不会失败,(2)我需要用Future.successful包装所有回复。

如何修复此代码?

  class Test extends Controller  {

    def test1 = Action.async { request =>

         val future = isPositive(-1)
         future.map { result =>
             Ok("OK, it's positive")
         }
         .recover { 
             case e => Ok(e.getMessage)
         }
    }

    def isPositive(i: Int) = Future {
        if (i<0)
            throw new Exception ( "Number is negative" )
        else
            i
    }

    def test2 = Action.async { request =>
        isPositiveWithTry(-1) match {
            case Success(s) => Future.successful(Ok("OK, it's positive (Try succeded)"))
            case Failure(f) => Future.successful(Ok(f.getMessage + " (Try failed)"))
        }
    }

    def isPositiveWithTry(i: Int) : Try[Future[Int]] = Try {
         isPositive(i)
    }

 }

2 个答案:

答案 0 :(得分:1)

isPositive方法中,Future

已经捕获了异常
def isPositive(i: Int) = Future {
        if (i<0)
            throw new Exception ( "Number is negative" )
        else
            i
}

在下面的代码中

def isPositiveWithTry(i: Int) : Try[Future[Int]] = Try {
     isPositive(i)
} 

isPositive已捕获所有广告素材,Try始终为success

所以,当i为负时。引发的异常由未来处理,尝试获得成功价值,结果尝试是成功的。所以你获得成功尝试内部失败的未来。

了解使用Grenade示例

假设将例外作为炸毁手榴弹。

假设FutureTry为两层。当手榴弹在Try[Future]的双层内被炸开时,即尝试围绕着未来,手榴弹在未来就会消失。

现在Future能够承受爆炸并成为失败的价值。由于未来已经承担了例外(手榴弹)损坏造成的损害。尝试将取得成功,但Try内部的值是未来失败的值。失败的未来价值只不过是提出的例外。

使用Future

时尝试是多余的

您可以将代码重构为低于一个

摆脱isPositiveWithTry

。不需要这种方法
 def isPositive(i: Int) = Future {
    if (i<0)
        throw new Exception ( "Number is negative" )
    else
        i
 }

def test2 = Action.async { request =>
    isPositive(-1).flatMap { _ =>
       Future.successful(Ok("OK, it's positive (Try succeded)"))
    }.recoverWith {
        case f: Throwable => Future.successful(Ok(f.getMessage + " (Try failed)"))
    }
}

再次test2也可以写成

 def test2 = Action.async { request =>
    isPositive(-1).map { _ =>
       Ok("OK, it's positive (Try succeded)")
    }.recover {
        case f: Throwable => Ok(f.getMessage + " (Try failed)")
    }
 }

如果isPositive返回Try

def isPositive(i: Int) = Try {
        if (i<0)
            throw new Exception ( "Number is negative" )
        else
            i
}

现在test2看起来像

def test2 = Action.async { request =>
        isPositive(-1) match {
            case Success(s) => Future.successful(Ok("OK, it's positive (Try succeded)"))
            case Failure(f) => Future.successful(Ok(f.getMessage + " (Try failed)"))
        }
    }

答案 1 :(得分:1)

情侣点:

1)您需要重写isPositive,使其不会通过Future包围自己。 Future正在捕捉异常。

def isPositive(i: Int) ={
  if (i<0)
    throw new Exception ( "Number is negative" )
  else
    i
}

2)如果你有一个Try并且想要一个Future,那么你可以在FutureFuture.fromTry的配套对象上使用该方法。这将需要Try并将其转换为Future的正确状态。