Reputation: 45466
Is there a Combine operator that will run a series of futures in sequence, running each to completion before starting the next?
I can do this with the very messy:
f1
.flatMap { _ in
f2
}.flatMap { _ in
f3
}.flatMap { _ in
// ...
}
but I'd prefer something like:
sequence(f1, f2, f3, ...)
In some frameworks, this would look like:
f1.then { f2 }.then { f3 }
Upvotes: 2
Views: 1842
Reputation: 33978
The key is to wrap the Future in a Deferred so it won't execute until it's time:
let f1 = Deferred { Future<Int, Error> { result in
}
}
let f2 = Deferred { Future<Int, Error> { result in
}
}
let f3 = Deferred { Future<Int, Error> { result in
}
}
let jobs = f1
.append(f2)
.append(f3)
cancellable = jobs.sink(receiveCompletion: { (completion) in
print("all three jobs done or one errored.")
}, receiveValue: { value in
print("value of job:", value)
})
In response to further questions in the comments:
You cannot rely on Deferred to defer closure execution until a subscriber comes in, because Deferred is a struct and would cause a new Future to be created every time there is a new subscriber.
That's precisely the point of deferred. To create a new Future every time there is a new subscriber and not before then. Another option would be to create the futures inside the appends.
let jobs = Future<Int, Error> { result in }
.append(Future<Int, Error> { result in })
.append(Future<Int, Error> { result in })
But then all three futures will execute their code at the same time. I'm assuming you don't want this.
Upvotes: 1