Ambiguous use of recover error while using PromiseKit

房东的猫 提交于 2019-12-10 17:57:03

问题


Running into a strange error when using recover while handling errors that can be thrown while executing a promise.

Chaining .recover with .then results in compilation if there is more than one statement in recover block.

Having single statement in recover block works and having recover alone (promise.recover{} without then works)

Attaching screenshots of single statement recover (which works) and multiple statement recover (which throws a compilation error with the message: Ambiguous use of recover(on:__:)

Any help on how to debug this would be appreciated.


回答1:


recover can return a Promise. If there is only 1 statement in your recover block then the compiler won't complain because there is only one line that could possibly return anything. When you add a second statement the compiler cannot infer which line returns something. Explicitly indicating that you are returning Void is one possible fix, assuming you don't intend to actually return anything.

func getNext() {
    taskGroup.getNext().then { data in
        self.initViewWithTask(data as! Task)
    }.recover { error -> Void in
        print("in recover")
        print("in recover 2")
    }
}

Explanation:

These four examples are functionally the same and will print One : Two : Three at the end. The closure in the first example is explicit in what parameter+type it will receive and what type be returned. Each subsequent example is less and less explicit about what is happening, so the complier must infer/deduce what is happening. The compiler can figure out what is happening because these examples are rather simple.

firstly {
    return Promise("One")
}.then { (result1: String) -> Promise<String> in
    return Promise("\(result1) : Two")
}.then { (result2: String) -> Promise<String> in
    return Promise("\(result2) : Three")
}.then { (result3: String) -> Void in
    print(result3)
    return
}

firstly {
    Promise("One")
}.then { (result1: String) -> Promise<String> in
    Promise("\(result1) : Two")
}.then { (result2: String) -> Promise<String> in
    Promise("\(result2) : Three")
}.then { (result3: String) -> Void in
    print(result3)
}

firstly {
    Promise("One")
}.then { result1 -> Promise<String> in
    Promise("\(result1) : Two")
}.then { result2 -> Promise<String> in
    Promise("\(result2) : Three")
}.then { result3 -> Void in
    print(result3)
}

firstly {
    Promise("One")
}.then { result1 in
    Promise("\(result1) : Two")
}.then { result2 in
    Promise("\(result2) : Three")
}.then { result3 in
    print(result3)
}

Now add a second line to the first closure. The compiler will be confused because it doesn't know what to return. It could be 999 or One. Even adding a simple print statement as you did will confuse the compiler and it will complain about ambiguous something. So either the compiler needs to get smarter (which it certainly could in the case of a simple print statement) or you need to be more explicit as to what is happening.

// ambiguous
firstly {
    Promise(999)
    Promise("One")
}.then { result1 in
    Promise("\(result1) : Two")
}.then { result2 in
    Promise("\(result2) : Three")
}.then { result3 in
    print(result3)
}

// clear
firstly {
    Promise(999)
    return Promise("One")
}.then { (result1: String) in
    Promise("\(result1) : Two")
}.then { result2 in
    Promise("\(result2) : Three")
}.then { result3 in
    print(result3)
}

As a side note... this really doesn't have anything to do with PromiseKit specifically. The examples could be written without PromiseKit. It is just understanding how the Swift complier interprets closures right now.




回答2:


With PromiseKit 6.11.0 (Swift 5.1/Xcode 11.1) you should use done instead of then if you don't want to return Thenable from closure. And in such case, you will not get "Ambiguous use of recover":

taskGroup.getNextTask().done { data in
    self.initViewWithTask(data as! Task)
}.recover { error in
    NSLog("in recover")
}


来源:https://stackoverflow.com/questions/34501537/ambiguous-use-of-recover-error-while-using-promisekit

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!