0

I have a Function that computes two sub-functions like this.

def someFutureMethod1(input: Int): Int = {
      input + 1
    }

def someFutureMethod2(input: Int): Int = {
      input + 12
    }

def method1(sx: Int): Future[Int] = Future {

      val future: Int = someFutureMethod1(sx)
      val future2: Int = someFutureMethod2(future)

future.andThen{
return future
}
future2.andThen{
return future2
}


}

Print(method1(10))


expected result:
11
23

I wanted to return the results as soon as First function calculated, and Update or append to the same result when second function calculated.

The Second function is dependent on the first function.As soon as first function executed successfully It should return the result. and First function result is passed to second function to compute the second function. If second function is computed then return the second function result alone.

Is there anyway to do this .?

Thanks in Advance !!

Learnis
  • 526
  • 5
  • 25
  • 2
    A `Future` has completed with a value or it is still working on it. One or the other. (Or it has failed.) I think the only way to get what you want is to have each `Future` modify the same `var` variable on completion. Very dangerous. Very bad idea. – jwvh Sep 17 '19 at 06:00
  • Possible duplicate of [Futures / Success race](https://stackoverflow.com/questions/20659406/futures-success-race) – pme Sep 17 '19 at 06:22
  • Can't you use Scala async to get what you want? – joesan Sep 17 '19 at 09:11
  • May be even a Scala Task can be of help! https://monix.io/docs/2x/eval/task.html – joesan Sep 17 '19 at 09:13
  • Can you explain exactly why and how do you expect this update to happen? What if other **Future** was already using the first returned value when the second method finishes? – Luis Miguel Mejía Suárez Sep 17 '19 at 11:18
  • I have updated the exepected result – Learnis Sep 17 '19 at 12:05
  • How do you expect the print to be executed two times? What if the print did not finished executing when the value changed? Have you considered all the concurrency issues of what you are asking? - I think what you really want is to execute the same callback two times, one time for **f1** and in parallel execute **f2** and pass the same callback to **f2**. – Luis Miguel Mejía Suárez Sep 17 '19 at 13:20

2 Answers2

1

check this code snippet (there are function signature modifications),

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global


def someFutureMethod1(input: Int): Future[Int] = Future {
  input + 1
}

def someFutureMethod2(input: Int): Future[Int] = Future {
  input + 12
}

def method1(sx: Int): Future[Int] = {
  val future1 = someFutureMethod1(sx)
  val future2 = someFutureMethod2(sx)

  for {
    f1 <- future1
    f2 <- future2
  } yield {
    f1 + f2 //add logic for your final output
  }
}
Pritish
  • 591
  • 3
  • 9
  • 4
    This really doesn't answer the question about returning the first result and then updating it with the second result. – Tim Sep 17 '19 at 07:31
  • i think in this code we are not returning as soon as it is calculating.We are waiting for second future to compute then we are returning . – Learnis Sep 17 '19 at 08:49
  • @Learnis; Not so. `method1()` does not wait. It returns immediately, but it returns a `Future` which might / might-not have completed yet. – jwvh Sep 17 '19 at 08:52
  • @jwvh The point is that this code doesn't return the result of method1 which is what the OP asks for, it only returns the result of method2. It is unclear what "return" means in the question, but the idea is to return the result of the first method and then update that to the result of the second method once it is available. – Tim Sep 17 '19 at 09:21
  • 1
    @Tim; Agreed. This code does not do what the OP asks for and, agreed, what the OP means by "return" is not clear. In fact, I think the question's most recent edit has muddied the water even further. But `method1()` returns the sum of **both** `someFutureMethod`s wrapped in a `Future`. So did the OP misinterpret the code or just describe it very poorly? Hard to say. – jwvh Sep 17 '19 at 10:02
0

Ok, so you could do something like this :

implicit val ec = Implicits.global

  def someFutureMethod1(input: AtomicInteger): Unit = {
    Future {
      input.addAndGet(1)
      println(input + " after method 1. And maybe also after method 2, because who knows.")
    }
  }

  def someFutureMethod2(input: AtomicInteger): Unit = {
    Future {
      input.addAndGet(12)
      println(input + " after method 2. And maybe also after method 1...")
    }
  }

  val at = new AtomicInteger(1)
  someFutureMethod1(at)
  someFutureMethod2(at)
  println(at + " at any point before or after the futures, so a pretty random value.")
  Thread.sleep(1000)
  println(at + " after all the futures. Probably.")

I added all the println so that the code is ready to copy paste and run. It will produce different outputs everytime you run it, which should your clue to run and flee !

I wouldn't accept this code in any code base I manage, and I wouldn't even accept it for a POC. It's totally unpredictable. Basically, the 4 instructions in method1 and method2 can execute in any order.

Note also that it doesn't guarantee that method1 is executed first.

If it's needed, you can change the code like this to make sure the first future is resolved before calling the second method :

  //Fluff removed

  def someFutureMethod1(input: AtomicInteger): Future[Unit] = {
    Future {
      input.addAndGet(1)
    }
  }

  def someFutureMethod2(input: AtomicInteger): Future[Unit] = {
    Future {
      input.addAndGet(12)
    }
  }

  def theUglyMethod(at: AtomicInteger) = someFutureMethod1(at).map {_ =>
    someFutureMethod2(at)
    at
  }

Once again, please don't do that ! ^^

C4stor
  • 8,355
  • 6
  • 29
  • 47
  • Do this is Fine What exactly i want is returning the response partly. – Learnis Sep 17 '19 at 09:42
  • I don't understand – C4stor Sep 17 '19 at 09:48
  • you are computing the method someFutureMethod1 and someFutureMethod2 right .? In that, once method someFutureMethod1 computation is done give the result to called one and method someFutureMethod2 should compute his task and append the result to old result – Learnis Sep 17 '19 at 09:55
  • Well, you can rearrage the method signatures however you want, at this point it's an implementation detail which you'll have to adapt to your own real case (which I suppose is not adding integers anyway). – C4stor Sep 17 '19 at 10:06
  • i dont think rearragement of your code will solve the problem – Learnis Sep 17 '19 at 11:01
  • Well, too bad then ! Good luck :-) – C4stor Sep 17 '19 at 12:12