PromiseKit 6.0 将捕捉到的错误传递给调用者

PromiseKit 6.0 passing catched errors to caller

根据迁移指南 PromiseKit 6.x 更改了他关于 catch 块的策略。在 PMK 4 中,catch 返回了它所附加的承诺。现在 catch 是链终止符。我明白为什么要进行这些更改,但是...

在我的代码库(与 PK4 相关)中,我从 catch returns 承诺中获得了一些好处。

func loginAndSync(withServerAddress address: String, port: String) -> Promise<()> {
    synchronizationService.stopAllRunningSingleSynchronizations()

    return
        authorizationService.save(serverAddress: address, andPort: port)
            .then {
                self.synchronizationService.startSingleFullSynchronization()
            }
            .then {
                self.authorizationService.markAsServerSynced()
            }
            .catch { error in
                log.error(error)
                _ = self.authorizationService.markAsServerUnsynced()
            }
}

在这个函数中,我做了一些在某些情况下会失败的逻辑。如果出现错误,catch 块应该做出一些逻辑,但我还想将此承诺(履行或拒绝)的结果发送给 loginAndSync 函数的调用者。例如,可以通过 ViewController 调用上述函数,在 ViewController 中,我想显示例如错误或成功对话框。

这就是一个 Promise 链需要两个 catches 的原因。一份用于 authorizationService,一份用于 UI

PromiseKit6 中是否有任何变通方法可以实现此目的?

编辑

我找到了两个解决方案(解决方法)。我创建了两个答案来将它们分开。未来的读者可以决定哪一个更好或提供新的。

我已将我的 Promise 链包裹在另一个 Promise 中:

func loginAndSync(withServerAddress address: String, port: String) -> Promise<()> {
    synchronizationService.stopAllRunningSingleSynchronizations()

    return Promise { seal in
        authorizationService.save(serverAddress: address, andPort: port)
            .then {
                self.synchronizationService.startSingleFullSynchronization()
            }
            .then {
                self.authorizationService.markAsServerSynced()
            }
            .done {
                self.coordinatorDelegate?.handleLoginServerSuccess()
                seal.fulfill(())
            }
            .catch {
                log.error([=10=])
                _ = self.authorizationService.markAsServerUnsynced()
                seal.reject([=10=])
            }
    }
}

应该可行,但我不知道这是不是一个好方法。

我发现 (IMO) 更好的解决方法。 PromiseKit6 引入了非常方便的方法 tap。我已经尝试用它来解决我的问题。

func loginAndSync(withServerAddress address: String, port: String) -> Promise<()> {
    synchronizationService.stopAllRunningSingleSynchronizations()

    return authorizationService.save(serverAddress: address, andPort: port)
        .then {
            self.synchronizationService.startSingleFullSynchronization()
        }
        .then {
            self.authorizationService.markAsServerSynced()
        }
        .tap { result in
            switch result {
            case .rejected(let error):
                log.error(error)
                _ = self.authorizationService.markAsServerUnsynced()
            default: break
            }
        }
        .done {
            self.coordinatorDelegate?.handleLoginServerSuccess()
        }
}

对于文档:

tap feeds you the current Result for the chain, so is called if the chain is succeeding or if it is failing

所以我可以为终止链的 Promise 当前状态提供自定义错误处理。 Promise 可以发送给发件人,在那里我可以做另一个 tap 或通过 catch.

终止链