将来在Scala中包装阻塞Try[T]的最佳方法是什么?

将来在Scala中包装阻塞Try[T]的最佳方法是什么?,scala,Scala,问题是,我有一个库,它有一个阻塞方法返回Try[T]。但是因为它是阻塞的,所以我想使用Future[T]使它成为非阻塞的。在以后的块中,我还想计算一些依赖于originblocking方法返回值的内容 但是如果我使用下面这样的东西,那么我的非阻塞将返回Future[Try[T]],因为Future[T]可能已经表示失败[U],所以我更愿意将异常传播到Future[T]is self def blockMethod(x: Int): Try[Int] = Try { // Some long

问题是,我有一个库,它有一个阻塞方法返回Try[T]。但是因为它是阻塞的,所以我想使用Future[T]使它成为非阻塞的。在以后的块中,我还想计算一些依赖于originblocking方法返回值的内容

但是如果我使用下面这样的东西,那么我的
非阻塞
将返回Future[Try[T]],因为Future[T]可能已经表示失败[U],所以我更愿意将异常传播到Future[T]is self

def blockMethod(x: Int): Try[Int] = Try { 
  // Some long operation to get an Int from network or IO
  throw new Exception("Network Exception") }
}

def nonBlocking(x: Int): Future[Try[Int]] = future {
  blockMethod(x).map(_ * 2)
}
下面是我尝试过的,我只是在
future{}
块中使用
.get
方法,但我不确定这是否是最好的方法

def blockMethod(x: Int): Try[Int] = Try { 
  // Some long operation to get an Int from network or IO
  throw new Exception("Network Exception") }
}

def nonBlocking(x: Int): Future[Int] = future {
  blockMethod(x).get * 2
}

这样做正确吗?或者有一种更为scala惯用的方式将t Try[t]转换为未来的[t]?

这里有一个不会阻塞的示例,请注意,您可能希望使用自己的执行上下文,而不是scala的全局上下文:

import scala.util._
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global

object Main extends App {

  def blockMethod(x: Int): Try[Int] = Try {
    // Some long operation to get an Int from network or IO
    Thread.sleep(10000)
    100
  }

  def tryToFuture[A](t: => Try[A]): Future[A] = {
    future {
      t
    }.flatMap {
      case Success(s) => Future.successful(s)
      case Failure(fail) => Future.failed(fail)
    }
  }

  // Initiate long operation
  val f = tryToFuture(blockMethod(1))

  println("Waiting... 10 seconds to complete")

  // Should return before 20 seconds...
  val res = Await.result(f, 20 seconds)

  println(res) // prints 100
}

我认为:Try&Future是一个一元结构,惯用的方式是一元构图(用于理解):

您需要为将来定义monad transformer[Try[\u]](库的代码):

和使用示例:

def blockMethod(x: Int): Try[Int] = Try {
  Thread.sleep(5000)
  if(x < 10) throw new IllegalArgumentException
  else x + 1
} 

import FutureT._  

// idiomatic way :)
val async = for {
  x <- futureTry { blockMethod(15) }
  y <- futureTry { blockMethod(25) }            
} yield (x + y) * 2  // possible due to using modan transformer  

println("Waiting... 10 seconds to complete")

val res = Await.result(async, 20 seconds)
println(res)

// example with Exception 
val asyncWithError = for {
  x <- futureTry { blockMethod(5) }
  y <- futureTry { blockMethod(25) }            
} yield (x + y) * 2  // possible due to using modan transformer  

// Can't use Await because will get exception 
// when extract value from FutureT(Failure(java.lang.IllegalArgumentException))
// no difference between Failure produced by Future or Try
asyncWithError onComplete {
  case Failure(e) => println(s"Got exception: $e.msg")
  case Success(res) => println(res)
}
// Output:
// Got exception: java.lang.IllegalArgumentException.msg
def blockMethod(x:Int):Try[Int]=Try{
线程。睡眠(5000)
如果(x<10)抛出新的IllegalArgumentException
其他x+1
} 
进口期货
//惯用方式:)
val async=for{

如果你知道你正在阻塞,你不是应该把代码包装在
阻塞
中吗
fromTry
方法对此有用吗?自我更正我之前的评论:
fromTry
实际上阻塞了,所以没有运气。我已经运行了更多的实验,实际上
未来(t.get)
似乎也不会阻塞线程。它看起来比flatMapping更简单。想法?有一个bug。通过
blockMethod(5)
更改
blockMethod(15)
会导致异常终止程序,最后一行
println(res)
未执行。谢谢David,我错过了异常行为的描述,请使用异常示例更新我的答案。
def blockMethod(x: Int): Try[Int] = Try {
  Thread.sleep(5000)
  if(x < 10) throw new IllegalArgumentException
  else x + 1
} 

import FutureT._  

// idiomatic way :)
val async = for {
  x <- futureTry { blockMethod(15) }
  y <- futureTry { blockMethod(25) }            
} yield (x + y) * 2  // possible due to using modan transformer  

println("Waiting... 10 seconds to complete")

val res = Await.result(async, 20 seconds)
println(res)

// example with Exception 
val asyncWithError = for {
  x <- futureTry { blockMethod(5) }
  y <- futureTry { blockMethod(25) }            
} yield (x + y) * 2  // possible due to using modan transformer  

// Can't use Await because will get exception 
// when extract value from FutureT(Failure(java.lang.IllegalArgumentException))
// no difference between Failure produced by Future or Try
asyncWithError onComplete {
  case Failure(e) => println(s"Got exception: $e.msg")
  case Success(res) => println(res)
}
// Output:
// Got exception: java.lang.IllegalArgumentException.msg