2013-08-15 34 views
28

Cách nào là sạch nhất để map số Exception của một thất bại Future trong scala?Bản đồ Ngoại lệ của một Thất bại tương lai

Nói rằng tôi có:

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

val f = Future { 
    if(math.random < 0.5) 1 else throw new Exception("Oh no") 
} 

Nếu tương lai thành công với 1, tôi muốn giữ điều đó, tuy nhiên nếu nó không thành công Tôi muốn thay đổi Exception đến một khác nhau Exception.

Điều tốt nhất tôi có thể đưa ra được biến đổi, tuy nhiên đòi hỏi tôi phải làm một chức năng không cần thiết đối với trường hợp thành công:

val f2 = f.transform(s => s, cause => new Exception("Something went wrong", cause)) 

Có bất kỳ lý do không có mapFailure(PartialFunction[Throwable,Throwable])?

+7

biến đổi là đúng cách để đi. bạn không cần tạo hàm s => s, chỉ cần chuyển vào '' identity'' –

+0

Chúc mừng. Tôi không biết về hàm 'identity'. Tôi chắc chắn sẽ có nhiều thời gian hơn trong đó sẽ có ích. – theon

Trả lời

26

Ngoài ra còn có:

f recover { case cause => throw new Exception("Something went wrong", cause) } 

Kể từ Scala 2.12 bạn có thể làm:

f transform { 
    case s @ Success(_) => s 
    case Failure(cause) => Failure(new Exception("Something went wrong", cause)) 
} 

hoặc

f transform { _.transform(Success(_), cause => Failure(new Exception("Something went wrong", cause)))} 
+1

Trong khi đây là một cú pháp rất rõ ràng, chúng ta vẫn phải 'ném' ngoại lệ mới, thay vì nhận bản đồ 'Throwable' thành 'Throwable'. Có một cái kết hợp cho điều đó không? – owensmartin

+0

@owensmartin Xem câu trả lời cập nhật của tôi. :) –

13

Bạn có thể thử recoverWith như trong:

f recoverWith{ 
    case ex:Exception => Future.failed(new Exception("foo", ex)) 
} 
+0

Future.failed không được đánh giá trên một ExeecutionContext: http://www.scala-lang.org/api/current/#scala.concurrent.Future$ thấy '' failed'' –

+0

@ViktorKlang, tôi phải nhầm lẫn sau đó. Tôi đã đưa ra giả định này khi xem xét phương thức 'impl.KeptPromise' class '' onComplete'. Trong đó, có hai dòng 'val preparedEC = executor.prepare; (mới CallbackRunnable (chuẩn bịEC, func)). executeWithValue (completedAs) '. Tôi cho rằng điều này ngụ ý rằng mặc dù chúng tôi đã đưa ra một giá trị rõ ràng rằng nó vẫn còn vì một lý do nào đó đã tấn công người thi hành. Nó luôn luôn có vẻ lạ đối với tôi và tôi đoán nó thực sự là vì tôi đã hiểu sai nó. Cảm ơn cho những người đứng đầu lên. – cmbaxter

+0

Cảm ơn câu trả lời. Sự do dự duy nhất của tôi với việc sử dụng 'recovery' /' recoveryWith' là khi tôi thấy nó, tôi ngay lập tức giả định rằng ý định là phục hồi từ một thất bại với kết quả thành công. Có lẽ đó chỉ là tôi. Mặc dù vậy họ là lựa chọn thay thế tốt, cảm ơn! – theon

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