如何避免尝试使用Future fromTry

时间:2018-05-21 18:43:29

标签: scala try-catch finally

我需要编写一个刷新流并将其关闭的未来。这是我试过的:

def close(ous: OutputStream) = Future.fromTry(Try {
    try {
      ous.flush()
    } finally {
      ous.close()
    }
  })

看起来很难看。 try{}finally{}内的Try。但我需要最后阻止以避免资源泄漏。有没有办法以不那么丑陋的方式重写代码?

4 个答案:

答案 0 :(得分:0)

这可能是我认为的一种选择。

def close(ous: OutputStream) = Future.fromTry(Try(ous.flush())) andThen {
    case Success(_) => println("do something here")
    case Failure(_) => ous.close()
}

答案 1 :(得分:0)

因为您已使用Try使用模式匹配结果Try{ stream.flush }并应用Try{ stream.close() }

例如,

  import java.io.{ByteArrayOutputStream, OutputStream}
  import java.util.Date
  import java.io.ObjectOutputStream
  import scala.concurrent.Future
  import scala.util.Try
  import scala.util.{Failure, Success}
  import scala.concurrent.ExecutionContext.Implicits.global

  def doSomeOperation: OutputStream => Future[String] = (outputStream: OutputStream) =>
    withCleanup(outputStream) {
      Future {
        //1/0
        outputStream.toString
      }
    }

  def withCleanup(outputStream: OutputStream)(fn: Future[String]): Future[String] = {

    val execution = fn

    execution onComplete {
      case Success(_) => cleanup(outputStream)
      case Failure(_) => cleanup(outputStream)
    }

    execution
  }

  def cleanup(outputStream: OutputStream): Try[Unit] = Try {
    outputStream.flush()
    println("flushed")
  } match {
    case _ => Try { 
      outputStream.close()
      println("closed")
    }
  }

然后调用该函数,它也会刷新并关闭你的流。

val stream = new ObjectOutputStream(new ByteArrayOutputStream())    
stream.writeObject(new Date())

scala> doSomeOperation(stream)
res18: scala.concurrent.Future[String] = Future(<not completed>)
flushed
closed

答案 2 :(得分:0)

我不清楚这是否真的更清洁:

def close(ous: OutputStream) = Future.fromTry(
  val flushed = Try { ous.flush() }
  val closed = Try { ous.close() }
  if (closed.isFailure) closed else flushed  // bubble up the correct error
)

注意:这几乎相当于this answer但不完全相同。主要是因为.close可能会失败,这必须封装在Try。

答案 3 :(得分:0)

Future已经捕获了返回Future.failed的异常,没有必要执行fromTry和block,所以你可以这样做:

Future { out.flush() }.andThen( _=> out.close )

Future { out.flush() }将异步刷新流,andThen将被调用,它将完成或失败。