2016-10-06 24 views
7

Làm cách nào để xử lý nếu một tương lai trả về ngoại lệ không thành công?Tiếp tục khi một Future.failed (ngoại lệ mới ("")) được trả lại trong Scala

Kịch bản là mã của tôi gọi getValue(), ánh xạ kết quả đến verifyValue() và sau đó tôi muốn có thể xử lý trường hợp kết quả của getValue() là Future.failed(new Exception("message")). Tuy nhiên khi tôi chạy điều này, nếu kết quả của getValue() là một tương lai không thành công nó chỉ ném ngoại lệ hơn là xử lý nó.

Có ai có bất kỳ đề xuất nào về cách tôi thực hiện việc này không?

def method(): Future[JsObject] = { 
    getValue().flatMap(verifyValue(_)) 
} 

def getValue(): Future[JsObject] = { 
    try { 
     value1 <- getValue1() 
     value2 <- getValue2(value1) 
    } yield { 
     value2 
    } 
} 

def verifyValue(result: Any): Future[JsObject] = { 
    result match { 
    case e: Exception => 
     getValue() 
    case json: JsObject => Future.successful(json) 
    } 
} 

Cập nhật: Tôi không nghĩ rằng tôi thực hiện điều này rõ ràng với câu hỏi ban đầu, nhưng lý do tại sao tôi flatMap giá trị là tôi không muốn dứt khoát phải đợi cho bất kỳ thị trường kỳ hạn trong mã của tôi, và do đó tôi không muốn sử dụng Future.onComplete {} để giải quyết giá trị.

Cập nhật 2: Một điều khác có thể không rõ ràng là nếu nó ném một ngoại lệ, tôi muốn gọi phương thức khác. Tôi không muốn nó chỉ xử lý ngoại lệ, nó sẽ ghi lại ngoại lệ và sau đó gọi một phương thức khác có giá trị trả về bằng cùng kiểu với getValue().

Trả lời

3

Những gì tôi đã kết thúc làm được bằng cách sử dụng phương pháp Future.fallbackTo().

def method(): Future[JsObject] = { 
    getValue().fallbackTo(method1()).fallbackTo(method2()).fallbackTo(method3()) 
} 

Nếu tương lai từ getValue() đầu tiên không thành công, nó sẽ gọi method1(). Nếu điều đó cũng không thành công, nó sẽ gọi method2() vv Nếu một trong các phương thức thành công, nó sẽ trả về giá trị đó. Nếu không có phương thức nào thành công, nó sẽ trả về tương lai không thành công từ getValue().

Giải pháp này không lý tưởng, vì tôi muốn bao gồm cả bốn ngoại lệ nếu tất cả các lần thử thất bại, nhưng ít nhất nó cho phép tôi thử lại phương thức getValue().

+1

Có vẻ như bạn muốn http://johnkurkowski.com/posts/accumulating-multiple-failures-in-a-ValidationNEL/ – Yawar

+0

Điều đó thật tuyệt vời! – annedroiid

+0

Xin cảm ơn, nhưng tôi quá lười biếng để đánh giá một câu trả lời xứng đáng, và bài đăng cũng có một công việc khá tốt giải thích các khái niệm :-) – Yawar

1
import scala.util.{Success, Failure} 

f.onComplete { 
    case Success(value) => // do sth with value 
    case Failure(error) => // do sth with error 
} 

Bạn có thể sử dụng onComplete trong phương pháp của bạn(), xem link bên dưới cho các tùy chọn khác như:

http://www.scala-lang.org/api/2.9.3/scala/concurrent/Future.html

6

Sử dụng recover hay recoverWith

phục hồi hoặc recoverWith được gọi là khi tương lai thất bại với một ngoại lệ. Trong khối khôi phục, bạn có thể đưa ra giá trị thay thế.

recoverWith không giống như recover mất tương lai của một cái gì đó

getValue().recover { case th => 
    //based on the exception type do something here 
    defaultValue //returning some default value on failure 
} 
+0

Nếu tôi cố gắng làm điều đó, getValue2 (value1) có lỗi biên dịch là "Loại không khớp, được mong đợi: Chuỗi, thực: Đối tượng", mặc dù trong quá trình khôi phục, tôi chỉ gọi getValue() một lần nữa. – annedroiid

+0

Vui lòng ngừng cập nhật điều này. Điều này không hoạt động, phục hồi và phục hồiVới phương thức chỉ xử lý ngoại lệ, bạn không thể gọi một phương thức khác có thể trả về với giá trị thành công, đó là mục tiêu của tôi. – annedroiid

+0

@annedroiid - bạn có thể đăng, trong câu hỏi của bạn, ít nhất là chữ ký loại của tất cả các phương pháp có liên quan và thông báo lỗi chính xác mà bạn đang nhận được không? Btw, 'recovery' và' recoveryWith' khá rõ ràng cho phép bạn tính toán và trả về giá trị thành công. Xem http://www.scala-lang.org/api/current/index.html#scala.concurrent.Tương lai @ phục hồi [U>: T] (pf: PartialFunction [Throwable, U]) (implicitexecutor: scala.concurrent.ExecutionContext): scala.concurrent.Future [U] – Yawar

Các vấn đề liên quan