2016-05-15 24 views
0
(for { 
    orderId <- ListT(extractParamFromHttp(request).toList) // extractParamFromHttp(request) returns Option[Long] 
    order <- ListT(serviceA.retrieve(orderId).map(_.toList)) // serviceA.retrieve(...) returns Future[Option[Order]] 
    items <- ListT(serviceB.retrieve(order.id).map(_.toList)) // serviceB.retrieve(...) returns Future[Seq[OrderItem]] 
    } yield items).map(...) // convert items to JSON and return as Future[Result] 

上述工程的代碼,當其中任何一個失敗,它返回一個零如果給出錯誤的輸入或缺少輸入,請獲取信息。我想要更具體的錯誤消息,而不是空的列表響應。例如,如果HTTP請求中的參數未找到。我想告訴發件人HTTP參數丟失或找不到給定的訂單ID。會使用EitherT或Either有幫助嗎?我應該怎麼做呢?感謝Scalaz:如何鏈未來[列表[A],選項[A]和未來[選項[A]和報告出錯個別

更新1

我解決它使用Scalaz EitherTEither(提示從Validation),並有輕微的變化粘貼在這裏我的解決方案,

import scalaz._ 
import Scalaz._ 
import scala.concurrent.Future 
import scala.concurrent.ExecutionContext.Implicits.global 

case class Order(id: Long, desc: String) 
case class Vendor(id: Long, name: String) 

def extractHeader(valid: Boolean): Option[String] = if (valid) Some("bob") else None 
def retrieveVendor(username: String, found: Boolean): Future[Option[Vendor]] = 
    if (found) Future.successful(Some(Vendor(103, "Bob Enterprise"))) else Future.successful(None) 
def retrieveOrders(vendorId: Long, found: Boolean): Future[List[Order]] = 
    if (found) Future.successful(List(Order(1, "Product 1"), Order(2, "Product 2"))) else Future.successful(List.empty[Order]) 

def output(result: Future[\/[String, AnyRef]]) = result.foreach { 
    case -\/(s) => println(s"Error: $s") 
    case \/-(ys @ x :: xs) => println(ys) 
    case \/-(s) => println(s) 
} 

def orders(valid: Boolean, userFound: Boolean, vendorFound: Boolean) = for { 
    username <- EitherT(Future.successful(extractHeader(valid) \/> "Bad headers")) // Option[String] 
    vendor <- EitherT(retrieveVendor(username, userFound).map(_ \/> "Bad username")) // Future[Option[Vendor]] 
    orders <- EitherT(retrieveOrders(vendor.id, vendorFound).map {     // Future[Seq[Order]]  
    case Nil => "Bad vendor".left 
    case xs => xs.right 
    })                    
} yield orders 

output(orders(false,false, true).run) 

參考答案非Scalaz解決方案

更新2

對於應用形式(如果需要)到該解決方案或更精心的解決方案,請參閱here

+1

看scalaz.Validation –

回答

0

我建議你折騰scalaz,它帶來任何價值,這種使用情況下,只是讓事情對你更加混亂。 不保持簡單的事情通常是這樣的問題的原因。

def ifExists[T, R](opt: Option[T], err: String)(f: T => Future[R]) = 
    opt.fold(Future.failed(new IllegalArgumentException(err))(f) 

for(
    order <- ifExists(extractParamFromHttp(request), "Missing param) { 
    serviceA.retrieve(_) 
    } 
    items <- ifExists(order, "Order not found") { serviceB.retrieve(_) } 
    result <- ... 
) yield result 

這返回Future[Result],即,完成時將包含任一的最終結果或指示失敗原因的異常。然後 主叫方可以與future.handle...檢查異常或處理成功和失敗與future.transformfuture.onComplete

+0

我不同意,我不應該問題複雜化的任何比他們更需要。對於這種情況,我發現scalaz解決方案是簡潔的,這些是我認爲可以很好地利用它們的少數幾個領域。我可能稍後改變:) – thlim

+0

「簡潔」?它實際上比我更長......並且不處理所有情況_(因此,你的問題在這裏)...... – Dima

相關問題