Reputation: 2315
I have 2 API endpoints; the latter depends on the result of the first.
The first end point is /api/v1/regions/
, which returns a list of region JSON like so
{
region_id: 1,
mayor_id: 9
},
{
region_id: 1,
mayor_id: 10
},
The second end point is /api/v1/mayor/<id>/
, which returns a JSON about the mayor. My workflow right now is to make the the first API call to get all the regions, then I want to make a bunch of API calls to the /mayor/
endpoint based on the IDs I get from the first end point. So in this example, I'd like to make 2 more calls:
/api/v1/mayor/9/
/api/v1/mayor/10/
I've already set up 2 functions to make each API call and successfully got the JSON back for each.
func fetchRegions() -> Promise<[Region]> {
}
func fetchMayor(id: String) -> Promise<Mayor> {
}
Now I'd like to see how I could chain all of these together. This is what I have so far:
var fetchedRegions: [Region] = []
firstly {
fetchRegions()
}.then { regions in
fetchedRegions = regions
}.then {
for r in fetchedRegions {
self.fetchMayor(id: r.mayor_id).then { mayor in
print(mayor)
}.catch { error in
}
}
}.catch { error in // Error: Missing return in a closure expected to return 'AnyPromise'
print(error)
}
Upvotes: 2
Views: 818
Reputation: 1570
You need to use when(fulfilled:)
operator. It waits for all promises in a set to fulfill.
when(fulfilled: promise1, promise2).then { results in
//…
}.catch { error in
switch error {
case URLError.notConnectedToInternet:
//…
case CLError.denied:
//…
}
}
Note:
If any of the provided promises reject, the returned promise is immediately rejected with that error.
Warning:
In the event of rejection the other promises will continue to resolve and, as per any other promise, will either fulfill or reject. This is the right pattern for getter style asynchronous tasks, but often for setter tasks (eg. storing data on a server), you most likely will need to wait on all tasks and then act based on which have succeeded and which have failed, in such situations use when(resolved:)
.
In according to your example it looks following (I explicitly defined all in/out parameters):
fetchRegions() // fetch your regions async
.then { (regions: [Region]) -> Promise<[Mayor]> in // here you got array [Region]
var tasks: [Promise<Mayor>] = [] // create an array of promises to fetch 'Mayor'
for region in regions {
tasks.append(self.fetchMayor(id: region.mayorId))
}
return when(fulfilled: tasks) // create promise which wait for all promises in a set to fulfill
}.then { (mayours: [Mayor]) -> Void in // here you will get an array of `Mayor`
// do here you want
}.catch { error in
print(error)
}
Upvotes: 1