目录:
- 一.what is operator ?
- 二.how this happend?
正文:
what is operator ?
先来看一个栗子:
import { of } from 'rxjs';
import { tap, pluck, mapTo } from 'rxjs/operators';
of({val: 1}).pipe(
tap(i => console.log(i)),
pluck('val'),
mapTo('hello world')
)
pipe中的一个个函数被称作operator,它定义了数据的处理步骤,并可以将处理后的值传递下去
how this happend ?
每个operator都会返回一个operation,operation其实是一个函数,拿tap举个栗子,在rxjs/src/internal/operator/tap.ts:
export function tap<T>(nextOrObserver?: PartialObserver<T> | ((x: T) => void),
error?: (e: any) => void,
complete?: () => void): MonoTypeOperatorFunction<T> {
return function tapOperatorFunction(source: Observable<T>): Observable<T> {
return source.lift(new DoOperator(nextOrObserver, error, complete));
};
}
class DoOperator<T> implements Operator<T, T> {
constructor(private nextOrObserver?: PartialObserver<T> | ((x: T) => void),
private error?: (e: any) => void,
private complete?: () => void) {
}
call(subscriber: Subscriber<T>, source: any): TeardownLogic {
return source.subscribe(new TapSubscriber(subscriber, this.nextOrObserver, this.error, this.complete));
}
}
从上面的代码可以看出:
-
tapOperatorFunction就是operation, 它的入参和回参都是Observable -
source是上一个Observable,这里指的是of({val: 1}),它的lift方法将创建一个包裹着tapOperatorFunction的Observable,lift()定义在rxjs/src/internal/Observable.ts:lift<R>(operator: Operator<T, R>): Observable<R> { const observable = new Observable<R>(); observable.source = this; observable.operator = operator; return observable; }它接受一个
operator,返回一个Observable,这里的this运用了隐式绑定,指向了of({val: 1})还记得在rxjs-pipeline中的一个庞然大物吗: 现在你应该知道lift方法其实创建一个新的包裹着当前操作符的Observale,并且通过source引用上一个Observale,从而形成了父子关系,并在最后返回了子节点,子节点又会被当成入参传入下一个操作符的operation中,这个流程被定义在rxjs/src/internal/util/pipe.ts:return function piped(input: T): R { return fns.reduce((prev: any, fn: UnaryFunction<T, R>) => fn(prev), input as any); };然后
tap的儿子又是pluck,并一直往下构建,最终形成了这个庞然大物 -
lift方法所接收的
Operator将由各自的操作符定义,这意味tap对应DoOperator类,而pluck和mapTo又有着不一样的,但它们都会实现Operator接口的call方法,它定义在rxjs/src/internal/Operator.tsexport interface Operator<T, R> { call(subscriber: Subscriber<R>, source: any): TeardownLogic; } -
call方法将会在最终的
subscribe阶段被调用,这是我们传入操作符的函数或者参数就会被调用,操作符也会发挥它真正的功能,具体过程请看rxjs subscribe原理