Promisekit: Conditional promises chaining.

Created on 18 Feb 2017  Â·  7Comments  Â·  Source: mxcl/PromiseKit

  • PromiseKit version: PromiseKit (4.1.0):
  • Xcode version: 8.1

Please format your code in triple backticks and delete this line before submitting your ticket. Failure to remove this line may result in mockery.

How I can make Optional promises chaining? e.g., I have two promises and I have to check second only by some conditions from first promise results:

promise1(). then { result -> Promise<Any>? in 
     if result.success {
           return promise2()
     }
     return nil
}
.then { secondResult -> Void in

}
.always {...}
.catch ...

But when I write something like this compiler thinks that type of is Promise<Any>?, not Any (bit "Any" I mean any other class/structure)

So, how I can make some kind of chaining? And there should be one always and one catch handlers as usual.

Most helpful comment

promise1().then { result in
    guard result else { throw NSError.canceledError }
    return promise2()
}.then {
    //…
}.catch { error in
    // cancelled errors do not reach `catch` handlers
}

All 7 comments

We don't support returning Promise? from then, mainly because, what should happen? Clearly you expected something to happen, but what exactly if I may ask?

You should throw or nest the second then in the first.

@mxcl ok, let me try to rephrase what I want to achieve.
I have chain of requests. E.g., 3 requests, each is embedded in Promise.

I make first request, get result inside .then {} and after I need to check this result
If condition == true - return next promise that calls next .then {} in chain. if condition is false - stop chaining and get direct to finally/always closure.

Can you suggest how to do it with your lib?
Cause I don't want to make it like callback hell like this

promise1().then { result in
  if result {
      promise2(). then {result2 in 
      }.catch....
  }
}.catch....
promise1().then { result in
    guard result else { throw NSError.canceledError }
    return promise2()
}.then {
    //…
}.catch { error in
    // cancelled errors do not reach `catch` handlers
}

Closed due to stagnation.

@mxcl Sort of related, could you recommend a pattern for the following scenario: Storing / retrieving an API token:

 - check if token on disk.
 - if on disk, check if expired.
 - if not expired, return token.
 - else if expired or not on disk:
    - retrieve from network.
    - save to disk.
    - return token.

I'm not sure if this should involve a compactMap or throwing an error and catching or an optional or what?

I'm imagining a single top level function: fetchToken() -> Promise<Token> and then several helpers: fetchTokenFromStorage() -> Promise<Token> and refreshToken() -> <Token> but tying these together is the problem..

func fetchFromDisk() {
    // if not on disk throw
}

func checkIfExpired() {
    // if expired throw else return the thing
}

func fetchCache() -> Promise<Foo> {
    return firstly {
        fetchFromDisk()
    }.then {
        checkIfExpired()
    }
}

func fetchFromNetwork() -> Promise<Foo> {
    return firstly {
        URSession.etc
    }.then { foo in
        save.map{ foo }
    }
}

firstly {
    fetchCache()
}.recover {
    fetchFromNetwork()
}

Please open new tickets for new questions in future.

@mxcl Thank you! I will :)

Was this page helpful?
0 / 5 - 0 ratings