1

Is there any difference between these two ways of completing a failed Future? If so, which way is considered to be more "correct"?

Calling Promise.failure:

def functionThatFinishesLater: Future[String] = {
    val myPromise = Promise[String]
    Future {
        // Do something that might fail
        if (failed) {
            myPromise.failure(new RuntimeException("message")) // complete with throwable
        } else {
            myPromise.success("yay!")
        }
    } (aDifferentExecutionContext)
    myPromise.future
}

Or just throwing an exception

def functionThatFinishesLater: Future[String] = {
    val myPromise = Promise[String]
    Future {
        // Do something that might fail
        if (failed) {
            throw new RuntimeException("message") // throw the exception
        } else {
            myPromise.success("yay!")
        }
    } (aDifferentExecutionContext)
    myPromise.future
}
alexkrishnan
  • 1,175
  • 8
  • 8
  • 1
    Possible duplicate of [**What is the Deferred Anti-Pattern and how do I avoid it?**](http://stackoverflow.com/questions/23803743/what-is-the-deferred-anti-pattern-and-how-do-i-avoid-it) – Benjamin Gruenbaum Aug 29 '14 at 09:40
  • @BenjaminGruenbaum That's useful info, but this question is definitely not a duplicate :) – acjay Aug 30 '14 at 14:42
  • @acjay as you can see - I did not vote to actually close it as such, I just found it amusing that the deferred anti pattern happens regardless of the language or implementation used :) – Benjamin Gruenbaum Aug 30 '14 at 14:43
  • It was definitely still helpful, seeing the antipattern in a different language helped drive the point home for me :) – alexkrishnan Aug 30 '14 at 18:53

1 Answers1

4

It looks to me like you're mixing paradigms. A Promise is an imperative way of completing a Future, but a Future can also be made completed by wrapping the computation in a Future constructor. You're doing both, which is probably not what you want. The second statement in both code fragments is of type Future[Promise[String]], and I'm almost certain you really want just Future[String].

If you're using using the Future.apply constructor, you should just treat the value produced as the Future, rather than using it to resolve a separate Promise value:

val myFuture = Future {
    // Do some long operation that might fail
    if (failed) {
        throw new RuntimeException("message")
    } else {
        "yay!"
    }
}

The way to use the Promise is to create the Promise, give its Future to some other piece of code that cares, and then use .success(...) or .failure(...) to complete it after some long running operation. So to recap, the big difference is that Future has to wrap the whole computation, but you can pass a Promise around and complete it elsewhere if you need to.

acjay
  • 34,571
  • 6
  • 57
  • 100
  • Sorry I think I left out some important info from my snippets there. I'm putting these snippets in a function that should be returning a future, and I've updated my question to reflect that. Am I still using Promise/Future incorrectly? (Thanks so much for your help!) – alexkrishnan Aug 29 '14 at 03:28
  • Yes, just drop the `Promise` altogether and let the `Future` constructor be the last statement in the function. And then let "yay!" by itself be the last value in the `Future`. It should basically look just like my example, but without assigning it to a variable. – acjay Aug 29 '14 at 16:43
  • Got it. The only time I should be using a Promise is if I'm completing it elsewhere. As for the question, I should just be throwing the exception to be handled later by future.onFailure. – alexkrishnan Aug 29 '14 at 22:44