mxcl / PromiseKit

Promises for Swift & ObjC.
MIT License
14.23k stars 1.46k forks source link

async(.promise) and promises (docs still accurate?) #1018

Open GarthSnyder opened 5 years ago

GarthSnyder commented 5 years ago

There's a blurb at the end of the Appendix document that reads:

So, if you want to start a chain by dispatching to the background, you have to use DispatchQueue.async:

DispatchQueue.global().async(.promise) {
    return value  
}.done { value in
    //…
}

However, this function cannot return a promise because of Swift compiler ambiguity issues. Thus, if you must start a promise on a background queue, you need to do something like this:

Promise { seal in
    DispatchQueue.global().async {
        seal(value)
    }  
}.done { value in
    //…
}

Or more simply (though with caveats; see the documentation for wait):

DispatchQueue.global().async(.promise) {
    return try fetch().wait()
}.done { value in
    //…
}

However, you shouldn't need to do this often. If you find yourself wanting to use this technique, perhaps you should instead modify the code for fetch to make it do its work on a background thread.

I wasn't sure of the exact issue behind this caution, so I spent some time trying to reproduce it, without much luck. Is it possible that current compilers handle this situation more smoothly?

E.g., this seems to work fine:

DispatchQueue.global().async(.promise) {
    return Promise.value(42)
}.then {$0}.done { value in
    print(value)
}.catch { _ in }

If the situation is in fact better now, it might be nice if the async(.promise) family provided its own unwrapping when the return type of the closure was a Promise or Guarantee so that, e.g., the return type of

queue.async(.promise) { Promise.value(42) }

would be Promise<Int> rather than Promise<Promise<Int>>.

It's potentially a breaking change, but since the docs have historically warned away from this, maybe not a big deal for PMK7?

mxcl commented 5 years ago

I imagine a multiple line attempt would be ambiguous, but possibly not (hopefully not).

In general one must do multiple line attempts since one liners are inferred differently (and more leniently).