代码之家  ›  专栏  ›  技术社区  ›  Darshan Kalola

如何避免在我没有编写的swift函数上出现回调地狱?

  •  2
  • Darshan Kalola  · 技术社区  · 6 年前

    我不希望这被误解为重复。我想处理来自Firestore(Firebase数据库,一个Google平台)的API调用所产生的回调地狱。我无法修改它们的函数声明,因此我假设必须用一些代码包装它们的函数。

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

    batch.commit { (error) in
        self.dismiss(animated: true) {
            if error == nil {
                self.eventCreatedSuccessfully()
                print("Event created successfully")
            } else {
                print(error!.localizedDescription)
            }
        }
    }
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Avi    6 年前

    用承诺来包装电话。任何一个流行的图书馆都能做到这一点。我想到的是PromiseKit,在(撰写本文时)的 https://github.com/mxcl/PromiseKit

    这是我为一个工作项目(它是开源的)编写的代码,它包装了一个完成的函数,并返回一个承诺,当调用完成时,该承诺将用结果发出信号。它使用内部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)
    }
    
        2
  •  0
  •   pacification    6 年前

    我在网上进行了研究,找到了期货和流等解决方案(…)

    在大多数情况下,期货和流都是关于 PromiseKit RxSwift 框架。

    如果只有大量闭包,请尝试使用PMK。它非常简单易用。PMK还有nice documentation section 在github上。

    RxSwift是更高级的级别,因为它要求您完全按照自己的范式编写代码——从服务器/firebase请求开始,以ui结束。此外,还有 good note 在PMK github,关于这两者的区别。

    另外,应该注意的是,google还有一个很好的库,叫做 promises .根据他们的 benchmarks 谷歌图书馆在几乎所有提名中都是领先者。