带你读《2022技术人的百宝黑皮书》——响应式编程的复杂度和简化(3)

简介: 带你读《2022技术人的百宝黑皮书》——响应式编程的复杂度和简化(3)

带你读《2022技术人的百宝黑皮书》——响应式编程的复杂度和简化(2)https://developer.aliyun.com/article/1339638?groupCode=taobaotech

在这个接口的实现中,数据回调最简单,在没有结束的情况下,多次回调的数据可以直接回调,问题是如何保证错误和完成有且仅有一次回调,且结果回调后不再回调数据,即:


 

什么时候回调错误?
什么时候回调完成?

 

 

如果我们认为一个接口出错,就回调错误,这是最简单的错误处理,只需要检查和设置结束状态,在没有结束时的第一个错误进行回调即可,注意,我们需要在userInfo的请求中也做类似的处理,并保证错误回调后不再执行任何回调。

 

完成的回调要比错误复杂的多,我们可以来思考一下:

  1. 首先,我们不能在listOrders的onComplete里面取回调完成,因为这里不能代表queryUserInfo这个接口也完成了;
  2. 其次,我们也不能简单的通过所有queryUserInfo都完成了就回调完成,因为listOrders在完成前仍然有可能返   回新的订单数据。

也就是说,这里的完成需要在queryUserInfo进行判断,并且也需要考虑外层请求的完成情况,比普通异步接口的级联要多了两个维度。这仅仅是2种接口4次请求,在真实的编程中,接口数量会多得多,并且需要把第4点加进来,线程/队列、并发、同步、缓冲区,还要处理新数据推送响应,再考虑调试、监控、排查,复杂度显然会继续大    幅增长,保证这个过程的正确性是一件痛苦的事情。

 

响应式编程的复杂度使用Rx/Combine简化响应式编程

 

为了解决这些问题,业界搞出了Reactive Streams规范(地址:https://www.reactive-streams.org/),也出现了若干的实现,都以工具库的形式提供,包括Rx系列、Reactor,以及苹果功能类似的Combine。作为一个iOS开  发,我对RxSwift和Combine比较了解,两者主要的区别在于Combine多了一个Subscription的抽象来协调Publisher和Subscriber之间的行为,尤其是Back   Pressure相关的控制,但总的来说,都提供了对于异步数据流的抽象和组合能力,用法上也很类似,这里以RxSwift为例来重写上面的过程。

 


第一步,实现一个将流式函数转换成Observable的工具类,这个是通用的,非常直观:

 

 

func makeObservable<Data>(f : @escaping StreamFunc<Data>) -> Observable<Data> {

 

2

 

Observable<Data>.create { observer in

3

 

f { data in

4

 

observer.onNext(data)

5

 

} _: { error in

6

 

observer.onError(error)

7

 

} _: {

8

 

observer.onCompleted()

9

 

}

10

 

return Disposables.create()

11

 

}

12

}

 

 

 

 

第二步,针对这个例子,将listOrder和queryUserInfo转换成StreamFunc形式,listOrder本来就是Stream-

Func,对queryUserInfo进行偏应用也可以转换为StreamFunc形式,这是具体接口相关的:

func makeStreamFunc(orders : [Order], userInfoService : UserService?) -> StreamFunc<[OrderOb- ject]> {
if let userInfoService = userInfoService {
// 核心是对queryUserInfo的userIds参数进行偏应用
let userInfoF : StreamFunc<[OrderObject]> = { onData, onError, onComplete in
let userIds = orders.map{$0.userId}
userInfoService.queryUserInfo(userIds: userIds, onData: { userInfoDict in
let orderObjects = orders.map { order in

 

8

 

OrderObject(order: order, userInfo: userInfoDict[order.userId])

9

 

}

10

 

onData(orderObjects)

11

 

}, onError: onError, onComplete: onComplete)

12

 

}

13

 

return userInfoF

14

 

} else {

15

 

return { onData, onError, onComplete in

16

 

onData(orders.map{OrderObject(order: $0)})

17

 

onComplete()

18

 

}

19

 

}

20

}

 

 

 

带你读《2022技术人的百宝黑皮书》——响应式编程的复杂度和简化(4)https://developer.aliyun.com/article/1339635?groupCode=taobaotech

相关文章
|
9月前
|
缓存 API 开发工具
带你读《2022技术人的百宝黑皮书》——响应式编程的复杂度和简化(2)
带你读《2022技术人的百宝黑皮书》——响应式编程的复杂度和简化(3)
|
9月前
|
Swift
带你读《2022技术人的百宝黑皮书》——响应式编程的复杂度和简化(5)
带你读《2022技术人的百宝黑皮书》——响应式编程的复杂度和简化(5)
|
9月前
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(4)
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(4)
|
9月前
|
安全
带你读《2022技术人的百宝黑皮书》——如何避免写重复代码:善用抽象和组合(4)
带你读《2022技术人的百宝黑皮书》——如何避免写重复代码:善用抽象和组合(4)
|
9月前
|
算法
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(3)
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(3)
|
9月前
|
网络协议
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(2)
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(2)
|
9月前
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(5)
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(5)
|
9月前
|
SQL 缓存 JSON
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(1)
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(1)
119 1
|
9月前
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(6)
带你读《2022技术人的百宝黑皮书》——性能优化之接口优化(6)
|
9月前
|
安全
带你读《2022技术人的百宝黑皮书》——如何避免写重复代码:善用抽象和组合(2)
带你读《2022技术人的百宝黑皮书》——如何避免写重复代码:善用抽象和组合(2)
带你读《2022技术人的百宝黑皮书》——如何避免写重复代码:善用抽象和组合(2)