Thomvis / BrightFutures

Write great asynchronous code in Swift using futures and promises
MIT License
1.9k stars 184 forks source link

Is there a way to sequence Futures of different types? #146

Closed wemped closed 8 years ago

wemped commented 8 years ago

I'm trying out this library and I'm running into an issue where I can't sequence() with two different Future types.

for example I have two classes that have these methods.

ClassOne.getOnes() -> Future<[ClassOne], NSError>
ClassTwo.getTwos() -> Future<[ClassTwo], NSError>

I am not able to do the following

let onesFuture = ClassOne.getOnes()
let twosFuture = ClassTwo.getTwos()

let futures =  [onesFuture, twosFuture]

futures.sequence().onSuccess { (theResults) in 
}

The sequence() method is not available to futures

I realize that if I just had the two classes in the example I could use zip, but my real use case involves many different classes.

Is there a way to do this that I'm not seeing?

Thanks!

Thomvis commented 8 years ago

This is a restriction/characteristic of Swift and has not much to do with BrightFutures itself. In Swift, all elements of an array should have the same type.

What you can do is wrap the different success value types of those futures in a single type (e.g. an enum). You can use future.map for that. After mapping all futures to the same value, you can use sequence(). Hope this helps!

wemped commented 8 years ago

Works great 👍 thanks for the tip!

For others that run into the issue, here is the solution.

Make an enum with all the types you need

enum FutureType{
case ClassOneType([ClassOne])
case ClassTwoType([ClassTwo])
}

change your functions that return Futures

ClassOne.getOnes() -> Future<FutureTypes, NSError>
ClassTwo.getTwos() -> Future<FutureTypes, NSError>

now sequence() should be available to futures in

let onesFuture = ClassOne.getOnes()
let twosFuture = ClassTwo.getTwos()

let futures =  [onesFuture, twosFuture]

futures.sequence().onSuccess { (arrayOfFutureTypes) in 
  for futureType in arrayOfFutureTypes{
     switch futureType{
     case .ClassOneType(let ones):
       print(ones)
       break

     case .ClassTwoType(let twos):
       print(twos)
       break
    }
  }
}