RxSwift中的map函数

由上一篇文章了解到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
         */

首先分析一下上面代码:

  • 有两个序列:源序列 obmap序列
  • 订阅这句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
    }

这个时候,我们需要注意,这里传了两个参数sourcetransform

  • 因为是源序列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
    }
}
  • 这里比较重要的操作是保存了初始化时,上一个方法传进来的两个参数sourcetransform,因为后面要用到,必须要保存。
  • 还有一个重要信息点是:Map继承自Producer,因为后面要走到他的subscribe方法

4、map初始化完成过后,就该来到它进行订阅了,所以来到最外层的subscribe方法:

 .subscribe{  // 需要外部订阅了,map函数b内部才会订阅源序列
                print("\($0)")
            }

5、因为map是一个Observable可观察序列,所以就来到了Observablesubscribe实现方法。

    public func subscribe(_ on: @escaping (Event) -> Void)
        -> Disposable {
            let observer = AnonymousObserver { e in
                on(e)
            }
            return self.asObservable().subscribe(observer)
    }

注意:因为最外面订阅方法不是用的那个带onNextsubscribe(onNext: ((Element) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil)这个方法,所以走的是上面的subscribe实现方法。

这里创建了一个对map函数序列的观察者AnonymousObserver,由上面第三步可知Map继承自Producer,所以接下来就来到了Producersubscribe方法,并将观察者AnonymousObserver传了过去。

6、来到Producersubscribe方法,后面就和前面文章讲的流程基本一样了:来到Producersubscribe方法中的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订阅了sinkMapSinkMapSink是源序列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)之后就又来到Producersubscribe方法中。

9、因为源序列ob订阅的是MapSink,所以最后来到MapSinkon方法:

   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)。

你可能感兴趣的:(RxSwift中的map函数)