rxjs of操作符生成的Observable对象的执行详细分析

186 阅读2分钟

代码:

const a = of([1, 2, 3]);
a.subscribe((data) => console.log('Fairy:' + data));

单步调试,首先执行of所在的index.ts:

of.js的实现很简单:

import { isScheduler } from '../util/isScheduler';
import { fromArray } from './fromArray';
import { scheduleArray } from '../scheduled/scheduleArray';
export function of(...args) {
    let scheduler = args[args.length - 1];
    if (isScheduler(scheduler)) {
        args.pop();
        return scheduleArray(args, scheduler);
    }
    else {
        return fromArray(args);
    }
}
//# sourceMappingURL=of.js.map

没有scheduler,走fromArray这条路:

fromArray.js的实现:

import { Observable } from '../Observable';
import { subscribeToArray } from '../util/subscribeToArray';
import { scheduleArray } from '../scheduled/scheduleArray';
export function fromArray(input, scheduler) {
    if (!scheduler) {
        return new Observable(subscribeToArray(input));
    }
    else {
        return scheduleArray(input, scheduler);
    }
}
//# sourceMappingURL=fromArray.js.map

这个subscribeToArray是一个函数构造器,接收一个数组,返回一个新的函数:

export const subscribeToArray = (array) => (subscriber) => {
    for (let i = 0, len = array.length; i < len && !subscriber.closed; i++) {
        subscriber.next(array[i]);
    }
    subscriber.complete();
};
//# sourceMappingURL=subscribeToArray.js.map

该函数和我们在应用代码里调用Observable对象的subscribe方法时传入的回调函数有何区别?

继续往下调试。

调用Observable对象的subscribe方法:

ObserverOrNext就是上图第63行的箭头函数,error和complete为undefined:

新建一个Subscriber对象:

subscriber的父类是subscription:

subscriber的destination是一个SafeSubscriber:

SafeSubscriber也是一个Subscriber:

这个emptyObservable啥实现也没有:

import { config } from './config';
import { hostReportError } from './util/hostReportError';
export const empty = {
    closed: true,
    next(value) { },
    error(err) {
        if (config.useDeprecatedSynchronousErrorHandling) {
            throw err;
        }
        else {
            hostReportError(err);
        }
    },
    complete() { }
};
//# sourceMappingURL=Observer.js.map
ExtensibilityExtensibility

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b92a7602893c45f58a612d671ba29094~tplv-k3u1fbpfcp-zoom-1.image)

所以toSubscriber返回的实际是一个subscriber对象:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/31ca5643ac6a4c16ac6f9987cf3fe7f7~tplv-k3u1fbpfcp-zoom-1.image)
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3892385a6f9b49289b5acbbcf15ec7ea~tplv-k3u1fbpfcp-zoom-1.image)




首先调用subscriber对象的add方法,目的是通过这个三元表达式,判断到底应该调用subscribe方法,还是trySubscribe方法:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/81740a36c5b0472db981725ec4f5a419~tplv-k3u1fbpfcp-zoom-1.image)


在我的Angular10,执行后者:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e313705184824566ac4e70ac299fc0f9~tplv-k3u1fbpfcp-zoom-1.image)


记住这个语义:Observable的subscribe方法,输入参数为subscriber:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7a029f905149483ea3d19385a66884ed~tplv-k3u1fbpfcp-zoom-1.image)

_trySubscribe调用_subscribe:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3d9ea8f687f84fb68a9b1510246aa17a~tplv-k3u1fbpfcp-zoom-1.image)

然后就执行到了之前用subscribeToArray返回的function内部:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f8dc1864fc654abf959736a791484926~tplv-k3u1fbpfcp-zoom-1.image)

注意在这个上下文里,我们既有输入,又有应用程序传入的subscribe函数,因此可以调用next了:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/49521925fd3544a3aa778b231ce623fa~tplv-k3u1fbpfcp-zoom-1.image)
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7576609375ff47bd860caa739bb95856~tplv-k3u1fbpfcp-zoom-1.image)




next和_next的区别就在于有个this.isStopped的判断:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8dbc8e0ace74428189cf065a4026b705~tplv-k3u1fbpfcp-zoom-1.image)

注意语义:Observable调用subscribe,而subscriber调用next.

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a16a56eaf97745a1a428343504a97983~tplv-k3u1fbpfcp-zoom-1.image)


subscriber的desination里包含了应用程序传入的callback:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/aff6fa5905164378aa4fbcfc0f60d42f~tplv-k3u1fbpfcp-zoom-1.image)
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/aa3c798e7a0b403080522ac913e7f440~tplv-k3u1fbpfcp-zoom-1.image)



subscriber的_tryOrUnsub函数里,最终调用应用程序的callback:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dd72f82b09004c35822d588804298a74~tplv-k3u1fbpfcp-zoom-1.image)
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e89f86dd0e4448d381bf67ab2f3f0583~tplv-k3u1fbpfcp-zoom-1.image)

更多Jerry的原创文章,尽在:"汪子熙":
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/47d1cac7bf1843c78fd455c72031cc17~tplv-k3u1fbpfcp-zoom-1.image)