使用 PromiseKit 时不明确地使用恢复错误

Posted

技术标签:

【中文标题】使用 PromiseKit 时不明确地使用恢复错误【英文标题】:Ambiguous use of recover error while using PromiseKit 【发布时间】:2015-12-28 22:11:06 【问题描述】:

在处理执行promise时可能抛出的错误时使用recover时遇到一个奇怪的错误。

如果recover 块中有多个语句,则将.recover 与.then 链接会导致编译。

在恢复块中使用单个语句并单独使用恢复(promise.recover 没有 then 有效)

附上单语句恢复(有效)和多语句恢复(引发编译错误并显示消息:Ambiguous use of recover(on:__:))的屏幕截图

任何有关如何调试的帮助将不胜感激。

【问题讨论】:

【参考方案1】:

recover 可以返回一个 Promise。如果您的恢复块中只有 1 条语句,那么编译器不会抱怨,因为只有一行可能返回任何内容。当您添加第二条语句时,编译器无法推断出哪一行返回了某些内容。明确指出您正在返回 Void 是一种可能的解决方法,假设您不打算实际返回任何内容。

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

解释:

这四个例子在功能上是一样的,最后都会打印One : Two : Three。第一个示例中的闭包明确说明它将接收什么参数+类型以及返回什么类型。随后的每个示例都对正在发生的事情越来越不明确,因此编译器必须推断/推断正在发生的事情。编译器可以弄清楚发生了什么,因为这些示例相当简单。

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)

现在在第一个闭包中添加第二行。编译器会感到困惑,因为它不知道要返回什么。可能是999One。即使像您那样添加一个简单的打印语句也会使编译器感到困惑,它会抱怨ambiguous something。因此,要么编译器需要变得更智能(在简单的 print 语句的情况下当然可以),要么你需要更明确地了解正在发生的事情。

// 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)

附带说明...这确实与 PromiseKit 没有任何关系。这些示例可以在没有 PromiseKit 的情况下编写。现在只是了解 Swift 编译器如何解释闭包。

【讨论】:

谢谢!!有效。但是仍然不明白为什么编译器对一个语句没有任何问题。第二条语句会怎样让编译器感到困惑。 稍后我会尝试提供一个示例。您可以在此期间查看此内容code.tutsplus.com/tutorials/…。 感谢详细的解释!!不查看闭包的最后一条语句提示编译器返回类型。仍然困惑为什么多个语句会混淆编译器。也是在快速闭包中隐式添加的 return 语句。 我认为编译器不应该假设最后一条语句是返回语句。这只是我的意见。不管是什么原因……苹果关闭文档说:Implicit returns from single-expression closures。 developer.apple.com/library/ios/documentation/Swift/Conceptual/…【参考方案2】:

对于 PromiseKit 6.11.0 (Swift 5.1/Xcode 11.1),如果您不想从关闭中返回 Thenable,则应使用 done 而不是 then。在这种情况下,您不会得到“Ambiguous use of recover”

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

【讨论】:

以上是关于使用 PromiseKit 时不明确地使用恢复错误的主要内容,如果未能解决你的问题,请参考以下文章

PromiseKit pod 安装正确,但 import PromiseKit 返回错误?

swift 3.0 转换添加到视图字典时不明确使用 tableView

使用 Alamofire 和 PromiseKit 使用 Swift 时出现 Void 错误(请求)

PromiseKit 分段错误:11

PromiseKit 6 错误无法转换错误

使用 PromiseKit 6 在 Swift 4.2 中缓存