Skip to content

Instantly share code, notes, and snippets.

@blixt
Created October 27, 2016 05:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save blixt/ca1ee704e5694700cbdfafebd4b0ea7d to your computer and use it in GitHub Desktop.
Save blixt/ca1ee704e5694700cbdfafebd4b0ea7d to your computer and use it in GitHub Desktop.
@discardableResult
public func then<U>(_ onFulfilled: @escaping (T) throws -> U) -> Promise<U> {
return self.thenImpl(onFulfilled, { throw $0 })
}
@discardableResult
public func then<U>(_ onFulfilled: @escaping (T) throws -> U, _ onRejected: @escaping (Error) throws -> U) -> Promise<U> {
return self.thenImpl(onFulfilled, onRejected)
}
@discardableResult
public func then<U>(_ onFulfilled: @escaping (T) throws -> Promise<U>) -> Promise<U> {
return self.then(onFulfilled, { throw $0 })
}
@discardableResult
public func then<U>(_ onFulfilled: @escaping (T) throws -> Promise<U>, _ onRejected: @escaping (Error) throws -> Promise<U>) -> Promise<U> {
// TODO: This creates several pointless Promise instances.
let promise = Promise<U>()
_ = self.thenImpl({ (try onFulfilled($0)).then(promise.resolve) }, { (try onRejected($0)).then(promise.resolve) })
return promise
}
private func thenImpl<U>(_ onFulfilled: @escaping (T) throws -> U, _ onRejected: @escaping (Error) throws -> U) -> Promise<U> {
...
}
@blixt
Copy link
Author

blixt commented Oct 27, 2016

I've avoided the issue of infinite loops (due to ambiguous method signatures) by creating a separate private method.

However, sometimes Swift thinks I should be providing a (T) -> Promise<U> closure instead of a (T) -> U closure when I provide a closure in the form { print("\($0) etc") }:

let urls = ["https://www.github.com/", "https://fika.io/"]
Promise.all(urls.map(fetch))
    .then({
        print("results:")
        for (i, url) in urls.enumerated() {
            let numLines = $0[i].components(separatedBy: "\n").count
            print("- \(url) returned \(numLines) lines of content")
        }
    })
    .catch({
        print("fail: \($0)")
    })
    .then({
        PlaygroundPage.current.finishExecution()
    })

Gives (on the first then):

error: missing return in a closure expected to return 'Promise<()>'

If Swift could correctly choose the other form automatically, there would be no compiler error (I can enforce it by adding value -> () in to the closure). Is there a way around this other than using different method names?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment