目录:
- 一.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; }
它接受一个
现在你应该知道lift方法其实创建一个新的包裹着当前操作符的operator
,返回一个Observable
,这里的this运用了隐式绑定,指向了of({val: 1})
还记得在rxjs-pipeline中的一个庞然大物吗: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.ts
export interface Operator<T, R> { call(subscriber: Subscriber<R>, source: any): TeardownLogic; }
-
call方法将会在最终的
subscribe
阶段被调用,这是我们传入操作符的函数或者参数就会被调用,操作符也会发挥它真正的功能,具体过程请看rxjs subscribe原理