복붙노트

[SCALA] 어떻게 스칼라 미래에 던져 예외를 잡아합니까?

SCALA

어떻게 스칼라 미래에 던져 예외를 잡아합니까?

나는 시간 제한이있는 블록을 실행하기위한 것입니다 거기 표준 스칼라 함수를 내 대답을 일한지? 예외가 미래에 던져진다면 문제로 실행했다.

  def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
    awaitAll(timeoutMs, future(f)).head.asInstanceOf[Option[T]]
  }

그래서

runWithTimeout(50) { "result" } should equal (Some("result"))
runWithTimeout(50) { Thread.sleep(100); "result" } should equal (None)

하지만 그것은 누설하지 않습니다 내 블록에서 예외가 발생하지만 섭취 한 경우 - 다음은 "..no 예외가 발생했다"실패 그래서

intercept[Exception] {
    runWithTimeout(50) { throw new Exception("deliberate") }
}.getMessage should equal("deliberate")

시스템 오류 메시지와 스택 추적을 가지고

<function0>: caught java.lang.Exception: deliberate

어디에서 인쇄 된 스칼라 런타임하지만 난 찾을 수 없습니다.

별도로 발생하는 경우 예외 전파를 잡아 다른 블록에서 포장 F에서 던져 awaitAll 및 / 또는 미래를 설득 할 수있는 방법은 무엇입니까?

해결법

  1. ==============================

    1.짧은 답변 : 아니오.

    짧은 답변 : 아니오.

    당신이 스레드 환경에서 작업 할 때 발신자의 예외에 대해 알고 싶어하기 때문에 예외가, 당신이 원하는 것을하지 않고, 예외가 미래의 스레드에서 발생합니다.

    당신은 예외가 무엇인지 알고 싶다면 대신, 당신은 어느 반환해야합니다 [예외, WhatYouWant] - 물론, 당신은 미래에서 그 예외를 잡아 그것을 포장해야합니다.

    scala> scala.actors.Futures.future{
      try { Right("fail".toInt) } catch { case e: Exception => Left(e) }
    }
    res0: scala.actors.Future[Product with Serializable with Either[Exception,Int]] = <function0>
    
    scala> res0()   // Apply the future
    res1: Product with Serializable with Either[Exception,Int] =
          Left(java.lang.NumberFormatException: For input string: "fail")
    
  2. ==============================

    2.면책 조항 : 형태 보증에 대한 I 작업

    면책 조항 : 형태 보증에 대한 I 작업

    아니면 .... 당신은 Akka를 사용할 수 있습니다 그리고 당신은 당신이 그것을 위해 농구를 통해 갈 필요없이 원하는 당신을 줄 것이다.

    val f: Future[Int] = actor !!! message
    

    그때

        f.get 
    

    배우에서 일어난 예외가 발생합니다

        f.await.exception 
    

    당신에게 옵션을 줄 것이다 [의 Throwable]

  3. ==============================

    3.@Rex 커의 제안을 통해 내 방식대로 작업, 내가 만든

    @Rex 커의 제안을 통해 내 방식대로 작업, 내가 만든

    object Timeout {
    
      val timeoutException = new TimeoutException
    
      def runWithTimeout[T](timeoutMs: Long)(f: => T) : Either[Throwable, T] = {
        runWithTimeoutIgnoreExceptions(timeoutMs)(exceptionOrResult(f)) match {
          case Some(x) => x
          case None => Left(timeoutException)
        }
      }
    
      def runWithTimeout[T](timeoutMs: Long, default: T)(f: => T) : Either[Throwable, T] = {
        val defaultAsEither: Either[Throwable, T] = Right(default)
        runWithTimeoutIgnoreExceptions(timeoutMs, defaultAsEither)(exceptionOrResult(f))
      }
    
      def runWithTimeoutIgnoreExceptions[T](timeoutMs: Long)(f: => T) : Option[T] = {
        awaitAll(timeoutMs, future(f)).head.asInstanceOf[Option[T]]
      }
    
      def runWithTimeoutIgnoreExceptions[T](timeoutMs: Long, default: T)(f: => T) : T = {
        runWithTimeoutIgnoreExceptions(timeoutMs)(f).getOrElse(default)
      }
    
      private def exceptionOrResult[T](f: => T): Either[Throwable, T] = 
        try { 
          Right(f) 
        } catch { 
          case x => Left(x)
        }
    }
    

    그래서

      @Test def test_exception {
        runWithTimeout(50) { "result" }.right.get should be ("result")
        runWithTimeout(50) { throw new Exception("deliberate") }.left.get.getMessage should be ("deliberate")
        runWithTimeout(50) { Thread.sleep(100); "result" }.left.get should be (Timeout.timeoutException)
    
        runWithTimeout(50, "no result") { "result" }.right.get should be ("result")
        runWithTimeout(50, "no result") { throw new Exception("deliberate") }.left.get.getMessage should be ("deliberate")
        runWithTimeout(50, "no result") { Thread.sleep(100); "result" }.right.get should be ("no result")
    
    }
    

    다시 말하지만, 나는 스칼라 초보자의 비트를, 그래서 피드백을 환영합니다.

  4. ==============================

    4.scala.concurrent.ops.future 예외 처리를 포함한다.

    scala.concurrent.ops.future 예외 처리를 포함한다.

    그래서, 대신 scala.actors.Futures.future, 수입 scala.concurrent.ops.future를 가져 오는 대신.

    그 간단한 변화는 가져 오기에 발신자의 호출이 예외를 다시 발생하는 갔지 거기 발생할 수 있습니다. 그것은 잘 작동합니다!

  5. ==============================

    5.또는 사용 Future.liftTryTry, 미래 [] 시도 [오브젝트]로 미래 [객체]에서 변합니다, 당신은 정상적으로 / 종료를 시도 [오브젝트]에 일치 예외 케이스 던져 (예)를 확인하고 로그인 할 수 있습니다

    또는 사용 Future.liftTryTry, 미래 [] 시도 [오브젝트]로 미래 [객체]에서 변합니다, 당신은 정상적으로 / 종료를 시도 [오브젝트]에 일치 예외 케이스 던져 (예)를 확인하고 로그인 할 수 있습니다

  6. ==============================

    6.당신은 캐치 예외 위해 방법 exceptionHandler를 오버라이드 (override) 할 필요가있다. 그래서 옵션은 exceptionHandler와 MyFutureActor을 만들어 귀하의 자신의 미래 방법을 정의하는 것입니다.

    당신은 캐치 예외 위해 방법 exceptionHandler를 오버라이드 (override) 할 필요가있다. 그래서 옵션은 exceptionHandler와 MyFutureActor을 만들어 귀하의 자신의 미래 방법을 정의하는 것입니다.

    편집 : 그것을 서브 클래스 화하는 것은 불가능하므로 FutureActor은 비공개입니다.

    또 다른 옵션은 예외가 일어 났을 때 알고 링크를 사용하는 것입니다.

    그러나, 나는 렉스 커의 접근 방식이 더 좋은 생각 - 그냥 예외를 잡을 것입니다 뭔가 기능을 래핑. 너무 나쁜 미래는 이미 그렇게하지 않습니다.

  7. from https://stackoverflow.com/questions/6229778/how-do-i-get-hold-of-exceptions-thrown-in-a-scala-future by cc-by-sa and MIT license