异步编程是开发APP的一个难点,多线程操作,线程的切换,多层嵌套callback,使得代码十分的混乱,难以理解。
func load(_ callback: (Value) -> Void) {
loadService.load { result in
let saveableItem = result.transfromToSaveableItem
saveQueue.async {
saveService.save(saveableItem) { saved in
let displayableItem = saved.tranfromToDisplayableItem
mainQueue.async {
callback(displayableItem)
}
}
}
}
}
github有很多直接或者间接能解决这个问题的方案,比如rxswift等函数响应式编程框架,通过observeOn, 可以轻松的切换线程,并且使用map,flatmap等操作符链式的操作结果,让我们轻松的写出结构清晰的代码。
Promise & Future
Promise&future是一个更简单的解决上述问题的模式。
使用promise还是rxswift?可以去看一下PromiseKit的这个讨论,点我
关于定义
Promise 最初提出于 1976 年,紧接着1977年又有人提出了一个概念相似的Future,Promise和Future通常结合起来使用。
a future is a read-only placeholder view of a variable, while a promise is a writable
-摘自wikipedia
这是Future结合Promise的核心思想。
实现一个Promise
Promise有三大要素:
-
保存当前状态的State
-
保存回调函数的Callbacks
-
控制线程安全的方式
github有很多版本的Promise的实现,其实都大同小异,基本都是根据以上三大要素变化而来,Promise的只读和可写部分的分离方式的不同,线程安全的实现的不同等。
class Promise<T> {
private var state: State<T> = .pending
private var callbacks: [Callback<T>] = []
private var serialQueue = DispatchQueue.init(label: "PromiseLocked")
...
...
}
状态以及Callback的定义:
enum State<Value> {
case pending
case fullfill(value: Value)
case reject(error: Error)
}
struct Callback<Value> {
var onFullfilled: ((Value) -> Void)?
var onRejected: ((Error) -> Void)?
var onQueue: DispatchQueue
}
通过一个串行队列来确保state与callbacks的线程安全,再加上链式的调用和转换函数,就构建了一个简单的Promise。
这样就可以写出类似下面的链式代码解决问题了:
loadService.load()
.then(transfromToSaveable)
.then(on: savedQueue, saveService.save)
.then(transfromToDisplay)
.then(on: MainQueue, display)
完整代码在这里可以找到。
网友评论