(十五)RxSwift之observeOn

776 阅读6分钟

使用 Scheduler 来让 Observable 支持多线程。observeOn 指定 Observable 在那个 Scheduler 发出通知

注意⚠️:一旦产生了 onError 事件, observeOn 操作符将立即转发。他不会等待 onError 之前的事件全部被收到。这意味着 onError 事件可能会跳过一些元素提前发送出去

下面让我们一起来看一下observeOn内部是如何实现的

先来看一段简单的代码

Observable.of(1,2,3,4,5,6,7,8,9,10)
    .observeOn(SerialDispatchQueueScheduler.init(internalSerialQueueName: "observeOnSerial"))
    .subscribe{print("observeOn",$0,Thread.current)}
    .disposed(by: self.bag)

一句一句来解析:

  • (一)Observable.of(1,2,3,4,5,6,7,8,9,10)

public static func of(_ elements: Element ..., scheduler: ImmediateSchedulerType = CurrentThreadScheduler.instance) -> Observable<Element> {
    return ObservableSequence(elements: elements, scheduler: scheduler)
}

这段代码会要求我们传入一些元素,然后会给一个默认的schedulerCurrentThreadScheduler 会返回一个ObservableSequence类型的序列

final private class ObservableSequence<Sequence: Swift.Sequence>: Producer<Sequence.Element> {
    fileprivate let _elements: Sequence
    fileprivate let _scheduler: ImmediateSchedulerType

    init(elements: Sequence, scheduler: ImmediateSchedulerType) {
        self._elements = elements
        self._scheduler = scheduler
    }

    override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
        let sink = ObservableSequenceSink(parent: self, observer: observer, cancel: cancel)
        let subscription = sink.run()
        return (sink: sink, subscription: subscription)
    }
}

该序列初始化时保存了原序列(elements) 和 调度环境(scheduler),并继承了Producer,实现了run方法。

  • (二).observeOn(SerialDispatchQueueScheduler.init(internalSerialQueueName: "observeOnSerial"))

public class SerialDispatchQueueScheduler : SchedulerType {

    let configuration: DispatchQueueConfiguration
    init(serialQueue: DispatchQueue, leeway: DispatchTimeInterval = DispatchTimeInterval.nanoseconds(0)) {
        self.configuration = DispatchQueueConfiguration(queue: serialQueue, leeway: leeway)
    }

    public convenience init(internalSerialQueueName: String, serialQueueConfiguration: ((DispatchQueue) -> Void)? = nil, leeway: DispatchTimeInterval = DispatchTimeInterval.nanoseconds(0)) {
        let queue = DispatchQueue(label: internalSerialQueueName, attributes: [])
        serialQueueConfiguration?(queue)
        self.init(serialQueue: queue, leeway: leeway)
    }
}

使用便利构造器初始化一个串行队列,并调用self.init将队列queue 和 延迟时间 leeway 保存在 self.configuration 中。

接下来,会带着创建好的队列来到 observeOn 函数:

public func observeOn(_ scheduler: ImmediateSchedulerType)
-> Observable<Element> {
    if let scheduler = scheduler as? SerialDispatchQueueScheduler {//串行
        return ObserveOnSerialDispatchQueue(source: self.asObservable(), scheduler: scheduler)
    }
    else {//并发
        return ObserveOn(source: self.asObservable(), scheduler: scheduler)
    }
}

由于我们创建的是串行队列,所以走上面对方法:

final private class ObserveOnSerialDispatchQueue<Element>: Producer<Element> {
    let scheduler: SerialDispatchQueueScheduler
    let source: Observable<Element>

    init(source: Observable<Element>, scheduler: SerialDispatchQueueScheduler) {
        self.scheduler = scheduler//<SerialDispatchQueueScheduler: 0x600003329b90>
        self.source = source//ObservableSequence<Array<Int>
    }

    override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
        let sink = ObserveOnSerialDispatchQueueSink(scheduler: self.scheduler, observer: observer, cancel: cancel)
        let subscription = self.source.subscribe(sink)
        return (sink: sink, subscription: subscription)
    }
}

ObserveOnSerialDispatchQueue 在初始化的时候保存了源函数(Observable.of(1,2,3,4,5,6,7,8,9,10))和我们初始化的串行队列(SerialDispatchQueueScheduler),并且同样继承了Producer,实现了自己的run方法。

  • (三).subscribe{print("observeOn",$0,Thread.current)}

这步是由源序列经过observeOn方法后会返回的ObserveOnSerialDispatchQueue来进行订阅的。 因为 ObserveOnSerialDispatchQueue 继承于producer,子类没有的会找父类,所以会来到Producersubscribe

override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
    if !CurrentThreadScheduler.isScheduleRequired {//当前线程被绑定
        // The returned disposable needs to release all references once it was disposed.
        let disposer = SinkDisposer()
        let sinkAndSubscription = self.run(observer, cancel: disposer)
        disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

        return disposer
    }
    else {
        return CurrentThreadScheduler.instance.schedule(()) { _ in
            let disposer = SinkDisposer()
            let sinkAndSubscription = self.run(observer, cancel: disposer)
            disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

            return disposer
        }
    }
}

pthread_getspecific(CurrentThreadScheduler.isScheduleRequiredKey) == nil返回为 true可知当前线程没有被绑定,走else方法。 然后携带闭包来到当前调度环境的schedule方法

public func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
    if CurrentThreadScheduler.isScheduleRequired {//没有绑定线程
        CurrentThreadScheduler.isScheduleRequired = false //走set方法 绑定一个

        let disposable = action(state)//state 外界闭包

        defer {//延长执行 所有事务执行之后将调度环境置nil
            CurrentThreadScheduler.isScheduleRequired = true
            CurrentThreadScheduler.queue = nil
        }

        guard let queue = CurrentThreadScheduler.queue else {
            return disposable
        }

        while let latest = queue.value.dequeue() {
            if latest.isDisposed {
                continue
            }
            latest.invoke()
        }

        return disposable
    }

    let existingQueue = CurrentThreadScheduler.queue

    let queue: RxMutableBox<Queue<ScheduledItemType>>
    if let existingQueue = existingQueue {//当前线程存在队列,赋值
        queue = existingQueue
    }
    else {//当前线程不存在队列,初始化一个
        queue = RxMutableBox(Queue<ScheduledItemType>(capacity: 1))
        CurrentThreadScheduler.queue = queue
    }

    let scheduledItem = ScheduledItem(action: action, state: state)
    queue.value.enqueue(scheduledItem)

    return scheduledItem
}

CurrentThreadScheduler.isScheduleRequired = false 通过 isScheduleRequiredset方法将当前的线程调度环境进行了绑定。然后会走let disposable = action(state)外界带过来的闭包。

let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

return disposer

self.run 会回到子类的run方法中,就会回到ObserveOnSerialDispatchQueuerun方法中

override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
    let sink = ObserveOnSerialDispatchQueueSink(scheduler: self.scheduler, observer: observer, cancel: cancel)
    let subscription = self.source.subscribe(sink)
    return (sink: sink, subscription: subscription)
}

带着observer:<AnonymousObserver<Int>: 0x600003329dd0>scheduler:<SerialDispatchQueueScheduler: 0x600003329b90>来进行sink的初始化。

final private class ObserveOnSerialDispatchQueueSink<Observer: ObserverType>: ObserverBase<Observer.Element> {
    let scheduler: SerialDispatchQueueScheduler
    let observer: Observer

    let cancel: Cancelable

    var cachedScheduleLambda: (((sink: ObserveOnSerialDispatchQueueSink<Observer>, event: Event<Element>)) -> Disposable)!

    init(scheduler: SerialDispatchQueueScheduler, observer: Observer, cancel: Cancelable) {
        self.scheduler = scheduler//<SerialDispatchQueueScheduler: 0x600003329b90>
        self.observer = observer//<AnonymousObserver<Int>: 0x600003329dd0>
        self.cancel = cancel
        super.init()

        self.cachedScheduleLambda = { pair in
            guard !cancel.isDisposed else { return Disposables.create() }

            pair.sink.observer.on(pair.event)

            if pair.event.isStopEvent {
                pair.sink.dispose()
            }

            return Disposables.create()
        }
    }

    override func onCore(_ event: Event<Element>) {
        _ = self.scheduler.schedule((self, event), action: self.cachedScheduleLambda!)
    }

初始化完成后会以sink为参数进行订阅let subscription = self.source.subscribe(sink) 由上面可以知道self.source为之前保存的源序列ObservableSequence进行订阅,由于 ObservableSequence也继承于Producer,所以又会来到Producersubscribe(第一次订阅是ObserveOnSerialDispatchQueue,这次是ObservableSequence

override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
    if !CurrentThreadScheduler.isScheduleRequired {//当前线程被绑定
        // The returned disposable needs to release all references once it was disposed.
        let disposer = SinkDisposer()
        let sinkAndSubscription = self.run(observer, cancel: disposer)
        disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

        return disposer
    }
    else {
        return CurrentThreadScheduler.instance.schedule(()) { _ in
            let disposer = SinkDisposer()
            let sinkAndSubscription = self.run(observer, cancel: disposer)
            disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

            return disposer
        }
    }
}

上次ObserveOnSerialDispatchQueue订阅时,已经绑定线程(CurrentThreadScheduler.isScheduleRequired = false),所以会走if的方法,self.run 会来到源序列 ObservableSequencerun方法.

final private class ObservableSequence<Sequence: Swift.Sequence>: Producer<Sequence.Element> {
    fileprivate let _elements: Sequence
    fileprivate let _scheduler: ImmediateSchedulerType

    init(elements: Sequence, scheduler: ImmediateSchedulerType) {
        self._elements = elements//1 2 3 4 5 6 7 8 9 10
        self._scheduler = scheduler//<CurrentThreadScheduler: 0x600003f681a0>
    }

    override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
        let sink = ObservableSequenceSink(parent: self, observer: observer, cancel: cancel)
        let subscription = sink.run()
        return (sink: sink, subscription: subscription)
    }
}

携带参数observer(<ObserveOnSerialDispatchQueueSink<AnonymousObserver>: 0x600001941980>)来到sink的初始化方法,super.initobserver保存,接下来会走sink.run

final private class ObservableSequenceSink<Sequence: Swift.Sequence, Observer: ObserverType>: Sink<Observer> where Sequence.Element == Observer.Element {
    typealias Parent = ObservableSequence<Sequence>

    private let _parent: Parent

    init(parent: Parent, observer: Observer, cancel: Cancelable) {
        self._parent = parent//<ObservableSequence<Array<Int>>: 0x600002835740>
        super.init(observer: observer, cancel: cancel)//<ObserveOnSerialDispatchQueueSink<AnonymousObserver<Int>>: 0x600001941980>
    }

    func run() -> Disposable {
        return self._parent._scheduler.scheduleRecursive(self._parent._elements.makeIterator()) { iterator, recurse in
            var mutableIterator = iterator
            if let next = mutableIterator.next() {
                self.forwardOn(.next(next))
                recurse(mutableIterator)
            }
            else {
                self.forwardOn(.completed)
                self.dispose()
            }
        }
    }
}
  • 这里返回的self._parent<ObservableSequence<Array<Int>>: 0x600002835740>
  • self._parent._schedulerObservableSequence_scheduler,也就是一开始我们创建序列是给的默认当前线程<CurrentThreadScheduler: 0x600003f681a0>

接下来 要来到CurrentThreadSchedulerscheduleRecursive方法,然而并没有,由于CurrentThreadScheduler继承ImmediateSchedulerType,所以来到ImmediateSchedulerTypescheduleRecursive方法中

public func scheduleRecursive<State>(_ state: State, action: @escaping (_ state: State, _ recurse: (State) -> Void) -> Void) -> Disposable {
    let recursiveScheduler = RecursiveImmediateScheduler(action: action, scheduler: self)
    
    recursiveScheduler.schedule(state)
    
    return Disposables.create(with: recursiveScheduler.dispose)
}

将外面穿进来的 state(源序列的迭加器IndexingIterator<Array<Int>>)和逃逸闭包,selfCurrentThreadScheduler传进来做参数,进行RecursiveImmediateScheduler的初始化 ,然后调用schedule方发,里面会有一些🔒之类的,有一句比较核心

if let action = action {
    action(state, self.schedule)
}

现在开始会往回执行action(state, self.schedule)会回到ObservableSequenceSinkrun方法的闭包中

var mutableIterator = iterator
if let next = mutableIterator.next() {
    self.forwardOn(.next(next))
    recurse(mutableIterator)
}
else {
    self.forwardOn(.completed)
    self.dispose()
}

这个迭代器包括所有的元素,和当前位置position,如果有下一个接着递归调用,没有就发送完成事件。 self.forwardOn 回来到 sinkforwardOn调用self._observer.onself._observer 就是之前保存的<ObserveOnSerialDispatchQueueSink<AnonymousObserver<Int>>: 0x600001941980> 所以接下来会走ObserveOnSerialDispatchQueueSinkonCore 方法

override func onCore(_ event: Event<Element>) {
    _ = self.scheduler.schedule((self, event), action: self.cachedScheduleLambda!)
}

self.scheduler.schedule 也就是SerialDispatchQueueSchedulerschedule

public final func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
    return self.scheduleInternal(state, action: action)
}

func scheduleInternal<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
    return self.configuration.schedule(state, action: action)
}

执行事件next(1)cachedScheduleLambda 的逃逸闭包将作为参数,传到 SerialDispatchQueueScheduler 初始化时保存self.configurationschedule方法中

func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
    let cancel = SingleAssignmentDisposable()

    self.queue.async {
        if cancel.isDisposed {
            return
        }
        cancel.setDisposable(action(state))
    }
    return cancel
}

observeOn中创建的队列异步执行闭包(ObserveOnSerialDispatchQueueSink中的cachedScheduleLambda),也就是观察者的回调。 然后会带着我们创建的队列和事件(pair)回到闭包中:

self.cachedScheduleLambda = { pair in
    guard !cancel.isDisposed else { return Disposables.create() }

    pair.sink.observer.on(pair.event)

    if pair.event.isStopEvent {
        pair.sink.dispose()
    }

    return Disposables.create()
}

然后调用pair.sink也就是ObserveOnSerialDispatchQueueSinkobserver.on方法(print("observeOn",$0,Thread.current)) 最后方法层层回收,一直到递归结束,发送completed事件

return self._parent._scheduler.scheduleRecursive(self._parent._elements.makeIterator()) { iterator, recurse in
    var mutableIterator = iterator
    if let next = mutableIterator.next() {
        self.forwardOn(.next(next))
        recurse(mutableIterator)
    }
    else {
        self.forwardOn(.completed)
        self.dispose()
    }
}

总结

调度器Scheduler是对线程进行了封装,subscribeOn操作符,不是用源序列直接订阅,而是封装了中间层sink,让源序列的元素在特定的队列中发出通知(pair.sink.observer.on(pair.event))。