Thomvis / BrightFutures

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

Execute an array of futures in parallel #140

Closed malcommac closed 8 years ago

malcommac commented 8 years ago

Are sequences executed sequentially? I've a number of future I would to execute in parallel (they are network requests) and I want to get notified when all of them are finished. Is it possible with BF? Thanks for your work

Thomvis commented 8 years ago

You can use sequence() defined on an array of futures. Whether the requests are executed in parallel depends on how you schedule your work, but parallelizing work is a very common use case. Please note that BF does not execute your work (although it does provide some helpers through the Queue type), it merely provides a way to communicate the result. If you want to know for sure, you can test it of course.

If you want more help, please share some code. Otherwise, feel free to close the issue.

tdesert commented 8 years ago

Hello ! How would you handle several futures of different types in a sequence ? Lets say you have two kinds of futures: Future<String, Error>, Future<Bool, Error> and want to execute your code once the two futures are completed ?

flyinghyrax commented 8 years ago

@tdesert for only two futures, I would use zip (example here).

If you know you will always have exactly N futures, you may be able to write your own version of zip that handles that many. But I do not know how to write that myself without some thought.

Handling a heterogenous sequence of arbitrary length is another problem - you will need some union type that includes the kinds of results you want to process, because your sequence can only have a single type; e.g. you must have one type T in the expression [Future<T, Error>].

tdesert commented 8 years ago

@mr-seiler Thanks for your answer. We finally made it simply using the tuple deconstruction with several zip calls:

future1.zip(future2).zip(future3).onSuccess { tuple in
    let ((result1, result2), result3) = tuple

    ....
}
Thomvis commented 8 years ago

Alternatively what you could do is change them into a void future, put them in an array and then use sequence to wait for all of them. Example:

let f1 = job1().andThen { /** update UI **/ }
let f2 = job2().andThen { /** update UI **/ }

let combinedF = [f1.asVoid(), f2.asVoid()].sequence()

The andThen is important if you want the combinedF to complete after the UI has been updated for all individual futures.