Promisekit: when(resolved:) with promises that return different types

Created on 27 Apr 2017  Â·  3Comments  Â·  Source: mxcl/PromiseKit

  • PromiseKit version: 4.1.7
  • Xcode version: 8.3.1

Hi, I have to join two separate chains of promises into one that depend on both. One of the two original promises, however, can fail and the code should continue its execution. Let me clarify with a little bit of code:

promiseThatMayFail:Promise<X> = ...
promiseThatMustSuceed:Promise<[Y]> = ...

finalPromise = when(resolved:[promiseThatMayFail, promiseThatMustSuceed]).then {...}

This code, however, doesn't compile because Xcode complains that all promises passed in the array to the when(resolved:) method are not of the same type. Using the syntax provided in the documentation (http://promisekit.org/docs/handbook/Functions.html#/s:F10PromiseKit4whenurFt8resolvedGSaGCS_7Promisex___GS0_GSaGOS_6Resultx___) also does not work.

Is when(resolved:) really supposed to work only with promises of the same type or am I doing something wrong?

PS: Everything works fine if I use when(fulfilled:)

Most helpful comment

Or don’t use when(resolved:); honestly, most of the time when people want to use it it is because they are using promises wrong. I have used when(resolved:) twice in 5 years of constantly using PromiseKit.

Like for example, you said you must recover from one of the two promises, but not the other, so maybe you should use recover:

let b = a.recover { err -> TypeOfA in 
   // error handling
   return someDefaultValueForTypeOfA
}

when(fulfilled: b, c).then { resultOfA, resultOfB in
    //…
}.catch {
   // this won't happen if a fails
}

This way if b fails you are still properly handling its error rather than potentially missing it.

All 3 comments

when(resolved:) takes an array, with Swift Array has to have a known type, thus the type has to be the same. when(fulfilled:) has a few convenience varieties that take a tuple instead, tuples can be specified with varying types.

So yes, as it stands, when(resolved:) requires the promises to be the same type as can be seen from the declaration.

As per the FAQ on this topic, the easiest way to get around this is to make all the promises Void by using asVoid() and then to unwrap the original promise’s value in your then:

when(resolved: [a.asVoid(), b.asVoid()]).then { _ in
    if let resultA = a.value {
        //…
    }
    if let resultB = b.value {
        //…
    }
}

Or don’t use when(resolved:); honestly, most of the time when people want to use it it is because they are using promises wrong. I have used when(resolved:) twice in 5 years of constantly using PromiseKit.

If you would like improvements to this domain, then you can contribute to when(resolved:) by copying the tuple methods provided for when(fulfilled:) or you can appeal to Swift Evolution and ask that some variety of generic-generic tuplizing functionality be added to Swift proper.

Or don’t use when(resolved:); honestly, most of the time when people want to use it it is because they are using promises wrong. I have used when(resolved:) twice in 5 years of constantly using PromiseKit.

Like for example, you said you must recover from one of the two promises, but not the other, so maybe you should use recover:

let b = a.recover { err -> TypeOfA in 
   // error handling
   return someDefaultValueForTypeOfA
}

when(fulfilled: b, c).then { resultOfA, resultOfB in
    //…
}.catch {
   // this won't happen if a fails
}

This way if b fails you are still properly handling its error rather than potentially missing it.

recoverwas exactly what I needed! Don't know why I overlooked it when I read the documentation. Thank you very much for the answer!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

drekka picture drekka  Â·  5Comments

matteonovelli picture matteonovelli  Â·  7Comments

emreond picture emreond  Â·  5Comments

Banck picture Banck  Â·  6Comments

adrianbg picture adrianbg  Â·  6Comments