Как избежать попытки с Future fromTry - PullRequest
0 голосов
/ 21 мая 2018

Мне нужно написать будущее, которое очищает поток и закрывает его.Вот что я попробовал:

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

Выглядит ужасно.try{}finally{} внутри Try.Но мне нужно наконец заблокировать, чтобы избежать утечки ресурсов.Есть ли способ переписать код не так безобразно?

Ответы [ 4 ]

0 голосов
/ 23 мая 2018

Future уже захватывает исключения, возвращающие Future.failed, нет необходимости делать fromTry и block, поэтому вы можете сделать:

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

(Future { out.flush() } будет асинхронно очищать поток, а andThen будетполучить вызов, когда он заканчивает работу или терпит неудачу.

0 голосов
/ 21 мая 2018

, поскольку вы уже используете 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
0 голосов
/ 22 мая 2018

Мне не ясно, действительно ли это чище:

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
)

Примечание. Это почти эквивалентно этому ответу , но не совсем.Главным образом, так как .close может дать сбой, и это должно быть заключено в Try.

0 голосов
/ 21 мая 2018

Это может быть вариант, я думаю.

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