api - Scala Future error handling with Either -
i writing wrapper api , want error handling applications problems. each request returns future in order see 2 options: using future[either]
or using exceptions fail future immediately.
here snippet both situations, response
future return of http request:
def handlerequesteither: future[either[string, string]] = { response.map { case "good_string" => right("success") case _ => left("failed") } } def handlerequest: future[string] = { response.map { case "good_string" => "success" case _ => throw new exception("failed") } }
and here snippet result in both cases:
handlerequesteither.oncomplete { case success(res) => res match { case right(rightres) => println(s"success $res") case left(leftres) => println(s"failure $res") } case failure(ex) => println(s"failure $ex") } handlerequest.oncomplete { case success(res) => println(s"success $res") case failure(ex) => println(s"failure $ex") }
i don't use exceptions, using future[either]
makes more verbose response afterwards, , if want map result object gets more complicated. way go, or there better alternatives?
let me paraphrase erik meijer , consider following table:
consider 2 features of language construct: arity (does aggregate 1 or many items?) , mode (synchronous when blocking read operations until ready or asynchronous when not).
all of imply try
constructs , blocks manage success or failure of block generating result synchronously. you'll control whether resources provides right answer without encountering problems (those described exceptions).
on other hand future
kind of asynchronous try
. means completes when no problems (exceptions) has been found notifying subscribers. hence, i don't think should have future of either
in case, second handlerequest
implementation right way of using futures.
finally, if disturbs throwing exception, follow approach of promises
:
def handlerequest: future[string] = { val p = promise[string] response.map { case "good_string" => p.success("success") case _ => p.failure(new exception("failed")) } p.future }
or:
case class reason(msg: string) extends exception def handlerequest: future[string] = { val p = promise[string] response.map { case "good_string" => p.success("success") case _ => p.failure(reason("invalid response")) } p.future }
i'd rather use second approach.
Comments
Post a Comment