Search code examples
iosswiftfirebasepromisepromisekit

PromiseKit For In Loop When Implementation


With Swift, I am trying to incorporate promises into my code with PromiseKit for the first time and am having difficulty understanding syntactically how to make this work.

My goal is to pipeline requests to Firebase for data and execute another method once an appended array is fulfilled with all the returned data. It seems the promise is resolved and the final method is run before the array is set with the data. I believe I should be using "when", but admittedly have trouble understanding the documentation.

Abbreviated, relevant code below:

getPosts(ids).done {
    runningFinalMethod(self.arr)
}

func getPosts(_ ids: [String]) -> Promise<Void>  {
    return Promise { seal in
        for id in ids {
            db.collection("data").whereField("id", isEqualTo: id).getDocuments(completion: { (dataForId, error) in                
                appendData(dataForId)
            })
        }
        seal.fulfill(())
    }
}

func appendData(_ dataForId: [data]) {                                  
    arr.append(contentsOf: dataForId)            
}

Solution

  • It is better that you use thenMap in cases like these where you are mapping multiple values asynchronously. Here is how you can achieve this

    func getPosts(_ ids: [String]) -> Promise<Void> {
        return Promise.value(ids).thenMap { id in
            Promise<data> { resolver in
                db.collection("data").whereField("id", isEqualTo: id).getDocuments { dataForId, error in
                    guard let error = error else { resolver.fulfill(dataForId) }
                    resolver.reject(error)
                }
            }
        }
        .done { allDataForIds in
            self.arr = allDataForIds
        }
        .catch { error in
            // handle error
        }
    }
    

    thenMap allows you to map individual values and then process the value with Promise. You can then collect all the value using done method, which has all the values from each of the collection promises. By the way, done method itself returns Promise<Void>, you could simply return that at the end.