ios - 如何避免我没有编写的 swift 函数的回调地狱?
问题描述
我不希望这被误解为重复。我想处理来自 Firestore(Firebase 的数据库,一个 Google 平台)的 API 调用引起的回调地狱。我不能修改他们的函数声明,所以我假设我必须用我的一些代码来包装他们的函数。
例如,在下面的代码中,该函数eventCreatedSuccessfully()
只能在异步函数完成后调用。eventCreatedSuccessfully()
还包含一个对具有闭包的firebase的函数调用,另一个函数依赖它等等......虽然这现在不会给我带来问题,但它可能会随着我的应用程序变得越来越大。我在线研究并从第三方框架中找到了诸如 Futures 和 Streams 之类的解决方案,但我不知道如何将它们集成到我无法控制的代码中(API 调用)。
batch.commit { (error) in
self.dismiss(animated: true) {
if error == nil {
self.eventCreatedSuccessfully()
print("Event created successfully")
} else {
print(error!.localizedDescription)
}
}
}
解决方案
将调用包装在 Promise 中。任何流行的库都可以解决问题。想到的是 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)
}
推荐阅读
- c++ - 试图保存矢量
在 bin 文件中并读取它给出了随机数据 - python - 在 Python 中显示重复的结果
- android - 有人可以教我如何在我当前的代码上应用回调吗
- javascript - TypeError:无法读取未定义的属性(读取“公会”)
- python - swi.nii 图像(医学图像)中的 3d numpy 数组中的 Np.min
- excel - Python 与 Excel
- javascript - 如何在 MongoDB 中搜索 2 个不同的集合(带分页)
- postgresql - 无需密码即可从 Wildfly 连接到 postgres
- stargazer - 在 Rstudio 中,有没有办法让“stargazer”输出包含小数的变量?
- c++ - 无法访问同一类中的私有成员