利用Swift实现一个响应式编程库

2020-01-09 00:04:54丽君

flatMap

flatMap 和 map 很相似,但也有一些不同,以可选型为例,Swif t是这样定义 map 和 flatMap 的:


public func map(_ transform: (Wrapped) throws -> U) rethrows -> U?
public func flatMap(_ transform: (Wrapped) throws -> U?) rethrows -> U?

flatMap 和 map 的不同主要体现在 transform 函数的返回值不同。map 接受的函数返回值类型是 U类型,而 flatMap 接受的函数返回值类型是 U?类型。例如对于一个可选值,可以这样调用:


let aString: String? = "¥99.9"
let price = aString.flatMap{ Float($0)}
// Price is nil

我们这里 flatMap 和 Swift 中数组以及可选型中的 flatMap 保持了一致。

所以我们的 flatMap 应该是这样定义:flatMap(_ transform: @escaping (Value) -> Signal) -> Signal。

理解了 flatMap 和 map 的不同,实现起来也就很简单了:


func flatMap(_ transform: @escaping (Value) -> Signal) -> Signal {
 let (sink, signal) = Signal.empty()
 var _dispose: Disposable?
 let dispose = subscribe { (result) in
  switch result {
  case .success(let value):
  let new = transform(value)
  _dispose = new.subscribe({ _result in
   sink(_result)
  })
  case .error(let error):
  sink(.error(error))
  }
 }
 if _dispose != nil {
 signal.objects.append(_dispose!)
 }
 signal.objects.append(dispose)
 return signal
}

现在我们可以模拟一个网络请求来测试 flatMap:


func users() -> Signal {
 let (sink, signal) = Signal.empty()
 DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+2) {
  let users = Array(1...10).map{ User(id: String(describing: $0)) }
  sink(.success(users))
 }
 return signal
 } 
func userDetail(with id: String) -> Signal {
 let (sink, signal) = Signal.empty()
 DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+2) {
 sink(.success(User(id: id, name: "jewelz")))
 }
 return signal
}
let dispose = users()
 .flatMap { return self.userDetail(with: $0.first!.id) }
 .subscribe { result in
 print(result)
}
disposes.append(dispose)
// Print: success(ReactivePrograming.User(name: Optional("jewelz"), id: "1"))

通过使用 flatMap ,我们可以很简单的将一个 Signal 转换为另一个 Signal , 这在我们处理多个请求嵌套时就会很方便了。

写在最后

上面通过100 多行的代码就实现了一个简单的响应式编程库。不过对于一个库来说,以上的内容还远远不够。现在的 Signal 还不具有原子性,要作为一个实际可用的库,应该是线程安的。还有我们对 Disposable 的处理也不够优雅,可以模仿 RxSwift 中 DisposeBag 的做法。上面这些问题可以留给读者自己去思考了。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对ASPKU的支持。