0

I am trying to chain some API calls and I think I am confusing some concepts. Would love some clarification & code samples.

I have implemented these functions...

func promiseFetchPayments(for accountId: String) -> Promise <[OperationResponse]> {
        return Promise <[OperationResponse]> { seal in
            
            payments(for: accountId) { (records, error) in
                
                if let recs = records {
                    seal.resolve(.fulfilled(recs))
                    return
                }
                
                if let e = error {
                    seal.reject(e)
                    return
                }
            }
        }
    }

and

func payments(for accountId: String, completion: @escaping (_ records: [OperationResponse]?, _ error: Error?) -> Void) {
        stellar.payments.getPayments(
            forAccount: accountId,
            order: Order.descending,
            limit: 10
        ) { response in
            switch response {
            case .success(let paymentsResponse):
                
                DispatchQueue.main.async {
                    completion(paymentsResponse.records, nil)
                }

            case .failure(let error):
                DispatchQueue.main.async {
                    completion(nil, error)
                }
            }
        }
    }

I am trying to use it like so:

firstly {
            promiseFetchPayments(for: "XXX")
        }.done { records in
            print(records)
        } .catch { error in
            print(error)
        }

Now this actually ^^^ works OK!!!! My problem is I want to be able to change done to then and be able to chain another function / response or many more.

But the error I keep getting is:

Cannot conform to Thenable.

I am looking for something very similar to this (I know the syntax isn't right just logically follow the chain....

firstly {
            stellar.promiseFetchPayments(for: "")
        }.done { records in
            print(records)
        }.then {
            // call some other method 
        }.done { data in 
          // more data 
        }.catch { error in
            print(error)
        }

Is this actually possible? Can't seem to get any tutorials on the interwebs to compile. Seems Swift compiler really doesn't like PMK syntax or something.

Any ideas?

  • Might want to consider switching over to Combine if you are not backwards compatible beyond iOS 13. – matt Feb 08 '21 at 21:29
  • @matt I was trying to exactly this with combine. But I found it quite difficult to use & super unintuitive. Really didn't jive with the syntax either, hard to wrap your head around. I am going to start reading your website https://www.apeth.com/UnderstandingCombine/toc.html and see maybe it can teach me better. – Adam Dahan Feb 09 '21 at 15:57
  • Let me know if it helps! It is _meant_ as a teaching tool. Also note that I have several times explained here how to chain async calls. See esp. https://stackoverflow.com/questions/59428026/how-to-replicate-promisekit-style-chained-async-flow-using-combine-swift/59430629?r=SearchResults&s=1|59.2365#59430629 – matt Feb 09 '21 at 18:57
  • @matt will do, thanks! – Adam Dahan Feb 09 '21 at 20:59

1 Answers1

0

The problem is because you're chaining off of a done, which doesn't like that you're trying to then do a call to then off of that.

Instead, you'll want to save the promise and use it for the later calls. You can do something like this:

let promise = firstly {
    stellar.promiseFetchPayments(for: "")
}

promise.done { records in
    print(records)
}

promise.then {
    // call some other method 
}.done { data in 
    // more data 
}.catch { error in
    print(error)
}

You can even return that promise from a method to use in other places, or pass it around to another method.

Gavin
  • 8,204
  • 3
  • 32
  • 42