由上一篇文章了解到map函数是一个映射的序列。现在具体看他怎么实现的。
let ob = Observable.of(1,2,3,4)
ob.map { (number) -> Int in
return number+2
}
.subscribe{ // 需要外部订阅了,map函数b内部才会订阅源序列
print("\($0)")
}
.disposed(by: disposeBag)
/*
输出结果:
next(3)
next(4)
next(5)
next(6)
completed
*/
首先分析一下上面代码:
- 有两个序列:源序列
ob
和map
序列 - 订阅这句
print("\($0)")
代码的是map
序列,而不是源序列ob
-
number+2
即为映射关系,可以理解为:函数表达式
然后通过断点,根据代码流程来进行分析:
1、首先来到:
public func map(_ transform: @escaping (Element) throws -> Result)
-> Observable {
return self.asObservable().composeMap(transform)
}
这个方法,看返回值是一个Observable
,就可以知道map函数也是一个可观察序列,所以它可以进行订阅print("\($0)")
2、然后来到:
internal func composeMap(_ transform: @escaping (Element) throws -> Result) -> Observable {
return _map(source: self, transform: transform) // 这里的self是原来的序列 ob
}
这个时候,我们需要注意,这里传了两个参数source
和transform
。
- 因为是源序列
ob
调用的这个方法,所以这里的self
是源序列ob
,即传给参数source
的是源序列ob
。 - 参数
transform
是一个逃逸闭包,即外面的闭包,那段函数表达式
{ (number) -> Int in
return number+2
}
3、然后来到map函数的初始化方法:
final private class Map: Producer {
typealias Transform = (SourceType) throws -> ResultType
private let _source: Observable
private let _transform: Transform
init(source: Observable, transform: @escaping Transform) {
self._source = source // 这里保存的source就是原来的序列 ob
self._transform = transform // transform 是 映射关系,即外界闭包,前面的 num+2
}
}
- 这里比较重要的操作是保存了初始化时,上一个方法传进来的两个参数
source
和transform
,因为后面要用到,必须要保存。 - 还有一个重要信息点是:
Map
继承自Producer
,因为后面要走到他的subscribe
方法
4、map
初始化完成过后,就该来到它进行订阅了,所以来到最外层的subscribe
方法:
.subscribe{ // 需要外部订阅了,map函数b内部才会订阅源序列
print("\($0)")
}
5、因为map
是一个Observable
可观察序列,所以就来到了Observable
的subscribe
实现方法。
public func subscribe(_ on: @escaping (Event) -> Void)
-> Disposable {
let observer = AnonymousObserver { e in
on(e)
}
return self.asObservable().subscribe(observer)
}
注意:因为最外面订阅方法不是用的那个带onNext
的subscribe(onNext: ((Element) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil)
这个方法,所以走的是上面的subscribe
实现方法。
这里创建了一个对map
函数序列的观察者AnonymousObserver
,由上面第三步可知Map
继承自Producer
,所以接下来就来到了Producer
的subscribe
方法,并将观察者AnonymousObserver
传了过去。
6、来到Producer
的subscribe
方法,后面就和前面文章讲的流程基本一样了:来到Producer
的subscribe
方法中的run
方法。
7、来到Producer
子类map
实现的的run
方法:
override func run(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == ResultType {
let sink = MapSink(transform: self._transform, observer: observer, cancel: cancel)
let subscription = self._source.subscribe(sink) // 外面Map订阅了 -> 源序列ob进行订阅MapSink -> 响应结果走到了MapSink.on方法
return (sink: sink, subscription: subscription)
}
这里有句流程中最关键的代码:
let subscription = self._source.subscribe(sink)
由上面第三步可知:这里的self._source
是源序列ob
,即源序列ob
订阅了sink
即MapSink
,MapSink
是源序列ob
的观察者。
所以这句代码的意思是:源序列ob
发送元素,然后响应的结果,传递给了MapSink
。
所以后面的步骤都是源序列ob
发送元素,然后响应给MapSink
,在MapSink
接受到响应之前,都不会进行后面的操作。
8、因为源序列Observable.of(1,2,3,4)
的初始化是下面这段代码:
public static func of(_ elements: Element ..., scheduler: ImmediateSchedulerType = CurrentThreadScheduler.instance) -> Observable {
return ObservableSequence(elements: elements, scheduler: scheduler)
}
而点进去,ObservableSequence
也是继承的Producer
。所以第七步self._source.subscribe(sink)
之后就又来到Producer
的subscribe
方法中。
9、因为源序列ob
订阅的是MapSink
,所以最后来到MapSink
的on
方法:
func on(_ event: Event) {
switch event {
case .next(let element): // 刚传进来的是源序列的 1
do {
let mappedElement = try self._transform(element) // 调用外面闭包,赋值过后,mappedElement变成了 3
self.forwardOn(.next(mappedElement)) // 发送新的元素,给map序列的观察者AnonymousObserver
}
- 在这里调用外界的闭包
transform
,将源序列ob
传过来的元素element
,经过函数表达式,变成新的元素mappedElement
。 - 将新的元素
mappedElement
再通过MapSink
发送出去,给map
序列的观察者AnonymousObserver
响应,即print("\($0)")
,打印出来。
10、后面的流程继续是:
源序列ob
发出下一个元素(2)--> 然后map
函数在MapSink
中调用闭包--> 将元素(2)映射成新的元素(4)--> MapSink
再发送新元素(4)给观察者AnonymousObserver,并打印出来。
总结:
map
函数订阅的过程中嵌套了:源序列订阅MapSink
的流程。
可以将整个过程看做是: y=f(g(x))
里面元素分别对应如下:
-
x
:源序列 -
g(x)
:map序列(中间主要是MapSink) -
f(g(x))
:外部map序列的订阅
即:
要求f(g(x))
的值(外部map序列的订阅),必须要先求g(x)
的值(map序列);
要求g(x)
的值,必须要先知道x
的值(即源序列),g(x)
的函数表达式就可以看做是map
的映射(即那个闭包number+2
)。