如何创建一个调用另一个服务并返回Future的方法?

时间:2014-07-29 09:56:05

标签: scala future

我想定义一个方法,它将返回Future。在这种方法中,它将调用另一个返回Future

的服务

我们已定义BusinessResult来代表SuccessFail

object validation {
  trait BusinessResult[+V] {
    def flatMap[T](f: V => BusinessResult[T]):BusinessResult[T]
    def map[T](f: V => T): BusinessResult[T]
  }

  sealed case class Success[V](t:V) extends BusinessResult[V] {
    def flatMap[T](f: V => BusinessResult[T]):BusinessResult[T] = {
      f(t)
    }
    def map[T](f: V => T): BusinessResult[T] = {
      Success(f(t))
    }
  }

  sealed case class Fail(e:String) extends BusinessResult[Nothing] {
    def flatMap[T](f: Nothing => BusinessResult[T]):BusinessResult[T] = this
    def map[T](f: Nothing => T): BusinessResult[T] = this
  }

}

并定义方法:

import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import validation._

def name: BusinessResult[String] = Success("my name")

def externalService(name:String):Future[String] = future(name)

def myservice:Future[Int] = {
  for {
    n <- name
    res <- externalService(n)
  } yield res match {
    case "ok" => 1
    case _ => 0
  }
}

但这不可编辑。 myservice中的代码无法返回Future[Int]类型。

我还尝试用name包裹Future

def myservice:Future[Int] = {
  for {
    nn <- Future.successful(name)
    n <- nn
    res <- externalService(n)
  } yield res match {
    case "ok" => 1
    case _ => 0
  }
}

哪个也不可编译。

我知道此代码中一定存在很多问题。如何调整它们以使其可编辑?

1 个答案:

答案 0 :(得分:1)

如果你用一些硬编码的字符串改变n它的作用,问题是在for comprehension中变量n的类型为BusinessResult[String],因为你可能已经知道你理解了desugarize到mapflatMapfilter,以便第一部分n <- name在名称上map去糖:

val test: BusinessResult[String] = name.map(x => x)

Intellij认为nString,但scala编译器不同意:

type mismatch;
[error]  found   : validation.BusinessResult[Nothing]
[error]  required: scala.concurrent.Future[Int]
[error]       n <- name
[error]         ^

简单的解决方案可能是添加一个getter方法来取回字符串并执行Option之类的操作:

object validation {
  trait BusinessResult[+V] {
    def flatMap[T](f: V => BusinessResult[T]):BusinessResult[T]
    def map[T](f: V => T): BusinessResult[T]
    def getVal: V
  }

  sealed case class Success[V](t:V) extends BusinessResult[V] {
    def flatMap[T](f: V => BusinessResult[T]):BusinessResult[T] = {
      f(t)
    }
    def map[T](f: V => T): BusinessResult[T] = {
      Success(f(t))
    }
    def getVal: V = t
  }

  sealed case class Fail(e:String) extends BusinessResult[Nothing] {
    def flatMap[T](f: Nothing => BusinessResult[T]):BusinessResult[T] = this
    def map[T](f: Nothing => T): BusinessResult[T] = this
    def getVal = throw new Exception("some message")
  }
}

def myservice: Future[Int] = {
  val value = name.getVal
  for {
    res <- externalService(value)
  } yield res match {
    case "ok" => 1
    case _ => 0
  }
}

请注意,自map String返回Char

后,您无法在for comprehension中提取名称