google / promises

Promises is a modern framework that provides a synchronization construct for Swift and Objective-C.
Apache License 2.0
3.8k stars 294 forks source link

all() doesn't work on more than 4 items. #109

Closed nielsz closed 5 years ago

nielsz commented 5 years ago
class MyA {}
class MyB {}

func getA() -> Promise<MyA> {
    return Promise<MyA> { fullfill, reject in
        print("promise MyA")
        fullfill(MyA())
    }
}

func getB() -> Promise<MyB> {
    return Promise<MyB> { fullfill, reject in
        print("promise MyB")
        fullfill(MyB())
    }
}
        all(
            getA(),
            getA(),
            getA(),
            getB()
        )
        .then { result in
            print("Got result!", result)

        }

This method works perfectly. But If I add one more item to the all() method, I can't compile anymore, with an error on the first item:

Cannot convert value of type 'Promise' to expected argument type 'Promise<_>'

Screenshot 2019-04-24 at 18 55 15

ghost commented 5 years ago

Hi @nielsz, currently, the max number of dissimilar value types that can be passed to all is 4: https://github.com/google/promises/blob/master/Sources/Promises/Promise%2BAll.swift#L148

Do you have a specific need to support 5 or more?

nielsz commented 5 years ago

Ah that's too bad. I couldn't find that limit in the documentation. I need to call 6 web-services, preferably at the same time.

shoumikhin commented 5 years ago

Hi Niels,

To make it clear, all() doesn't initiate promises execution in any way, so you can't expect the promises you pass into all() start doing their work simultaneously at that moment. Moreover, you can even pass an already resolved promise to all(), if needed. all() just allows you to wait for a bunch of different promises and get notified when all of them are fulfilled, whenever that happens.

So, you can effectively leverage a combination of all() with nearly the same outcome as if all() really supported 5 or more heterogeneous arguments. For example:

all(all(p1, p2, p3), all(p4, p5, p6)).then { results in
  let ((a1, a2, a3), (a4, a5, a6)) = results
  print(a1, a2, a3, a4, a5, a6)
}

Another option would be extending Promise+All.swift (and Promises+AllTests.swift, of course) to allow a few more arguments. That is somewhat tedious and boilerplate, but feel free to send a PR our way, if that's what you'd prefer.

Thanks.

ghost commented 5 years ago

@nielsz closing this issue, but feel free to submit a PR if you need the additional functionality for all. Thank you!

fitsyu commented 5 years ago

Ah that's too bad. I couldn't find that limit in the documentation. I need to call 6 web-services, preferably at the same time.

It is nice to have the limit explicitly stated there. :)

shoumikhin commented 5 years ago

@fitsyu we're happy to accept a PR with the proposed change :)