iosswiftpromisekit

Using PromiseKit I want to make multiple API calls


I'm using PromiseKit in my project and I need to do batch/multiple calls to the API and wait for all responses. Any ideas how to do this? I'm pretty new to PromiseKit, and didn't find anything regarding this on their Github (probably didn't see or understand it)

What I'm trying at the moment and failing is:

    let ids = [1, 2, 3, 4, 5]
    firstly {

               getURLPathsFor(ids) // maybe I'm doing this wrong - this returns a Promise<[String]>

            }.thenMap { url in

                ApiManager.shared.request(url, method: .delete)

            }.done { _ in
                seal.fulfill(())
            }.catch { error in
                seal.reject(error)
            }

    func getURLPathsFor(_ ids: [UInt]) -> Promise<[String]> {
        let path = "/somePath"
        var URLs = [String]()
        return Promise { seal in
            ids.forEach { uid in
                AppConfigManager.shared.getApiUrl(path: path, uid).done { url in
                    URLs.append(url)
                    seal.fulfill(URLs)
                }.catch { error in
                    seal.reject(error)
                }
            }
        }
    }

Any help would be great, really stuck with this one.


Solution

  • So I managed to achieve the batch calls I wanted using PromiseKit and handling all errors together:

    private func batchDeleteItem(with itemId: UInt) -> Promise<(UInt, AppError?)> {
        return Promise { seal in
            firstly {
                AppConfigManager.shared.getApiUrl(path: Constants.Api.deleteItemRequestPath, itemId)
            }.then { url in
                ApiManager.shared.request(url, method: .delete)
            }.done { _ in
                seal.fulfill((itemId, nil))
            }.catch { error in
                guard let appError = error as? AppError else {
                    seal.reject(error)
                    return
                }
                seal.fulfill((itemId, appError))
            }
        }
    }
    

    I call this method in a map, and in order to collect the ids of items that couldn't be deleted, I treat the catch with fulfill as wel - rejecting only server side error (this is what I needed for my case) :

    return Promise { seal in
    
            let promises = ids.map { itemId in
                batchDeleteNode(with: itemId)
            }
    
            when(fulfilled: promises).done { results in
                seal.fulfill(results)
            }.catch { error in
                seal.reject(error)
    
            }
        }
    

    And to have all the errors grouped and waited for I use when(fulfilled: promises).done {...}

    I'm not saying it's perfect but seems to work very well, and I learned a lot in the process regarding PromiseKit.