如何避免我没有编写的快速函数的回调地狱?

时间:2018-05-09 14:14:02

标签: ios swift firebase callback google-cloud-firestore

我不希望这被误解为副本。我想处理来自Firestore的API调用(Firebase,Google平台的数据库)引起的回调地狱。我不能修改它们的函数声明,所以我假设我必须用我的一些代码包装它们的函数。

例如,在下面的代码中,函数eventCreatedSuccessfully()只能在异步函数完成后调用。 eventCreatedSuccessfully()还包含对firebase的函数调用,该函数调用有一个闭包,另一个函数依赖于等等......虽然现在这不会给我带来问题,但它可能随着我的App越来越大而变得越来越大。我在网上研究并从第三方框架中找到了Futures和Streams等解决方案,但我不知道如何将它们集成到我无法控制的代码中(API调用)。

batch.commit { (error) in
    self.dismiss(animated: true) {
        if error == nil {
            self.eventCreatedSuccessfully()
            print("Event created successfully")
        } else {
            print(error!.localizedDescription)
        }
    }
}

2 个答案:

答案 0 :(得分:1)

将电话包裹在承诺中。任何流行的图书馆都可以解决问题。想到的是PromiseKit(在撰写本文时)https://github.com/mxcl/PromiseKit可用。

这是我为工作项目(它的开源)编写的代码,它包含一个完成的函数,并返回一个Promise,它将在调用完成时通知结果。它使用内部Promise实现,但该过程可以适应其他实现。

public func promise<Return>(_ task: (@escaping (Return?, Error?) -> ()) -> ()) -> Promise<Return> {
    let p = Promise<Return>()

    task { (value: Return?, error: Error?) -> Void in
        if let error = error {
            p.signal(error)
        }

        if let value = value {
            p.signal(value)
        }
    }

    return p
}

预计会因某种结果或错误而调用完成。根据您的用例进行调整。

以下是一个示例用法。

public typealias BalanceCompletion = (Balance?, Error?) -> Void

func balance(completion: @escaping BalanceCompletion) {
    guard deleted == false else {
        completion(nil, KinError.accountDeleted)

        return
    }

    Stellar.balance(account: stellarAccount.publicKey!, asset: asset, node: node)
        .then { balance -> Void in
            completion(balance, nil)
        }
        .error { error in
            completion(nil, KinError.balanceQueryFailed(error))
    }
}

func balance() -> Promise<Balance> {
    return promise(balance)
}

答案 1 :(得分:0)

  

我在网上研究并找到了Futures和Streams(...)

等解决方案

在大多数情况下,期货和流都是PromiseKitRxSwift框架。

如果您只有大量关闭,请尝试使用PMK。它非常简单易用。 PMK在github上也有很好的documentation section

RxSwift是更高级的,因为它要求你完全编写代码到自己的范例 - 从server / firebase请求开始,以ui结束。此外,PMK github还有good note关于这两者的差异。

另外,应该注意的是,Google也有一个很好的名为promises的库。根据他们的benchmarks谷歌图书馆几乎所有提名都是领导者。