在上一篇我们简单实现了Observable.create,那么如何在此基础上实现Map操作呢。
对于如下代码,我们希望输出2,4
Observable.create((observer) => {
observer.next(1);
observer.next(2);
})
.map(value => value * 2)
.subscribe((value) => console.log(value));
修改Observable.js,如下:
import { toSubscribe } from "./toSubscriber";
import { higherOrderMap } from "./operator/map";
class Observable {
constructor(subscribe) {
this.source = null;
this.operator = null;
if (subscribe) {
this._subscribe = subscribe;
}
}
static create(subscribe) {
return new Observable(subscribe);
}
lift(operator) {
const observable = new Observable();
observable.source = this;
observable.operator = operator;
return observable;
}
_subscribe(subscribe) {
return this.source.subscribe(subscribe);
}
subscribe(observerOrNext) {
const { operator } = this;
const sink = toSubscribe(observerOrNext);
if (operator) {
operator.call(sink, this.source);
} else {
this._trySubscribe(sink);
}
}
_trySubscribe(sink) {
return this._subscribe(sink);
}
}
Observable.prototype.map = function (project) {
return higherOrderMap(project)(this);
};
export default Observable;
map.js:
import { Subscriber, } from "../Subscriber";
class MapSubscribe extends Subscriber {
constructor(destinationOrNext, project) {
super(destinationOrNext);
this.project = project;
}
_next(value) {
let result = this.project.call(this, value);
this.destination.next(result);
}
}
class MapOperator {
constructor(project) {
this.project = project;
}
call(subscribe, source) {
return source.subscribe(new MapSubscribe(subscribe, this.project));
}
}
export function higherOrderMap(project) {
return (source) => {
if (typeof project !== 'function') {
throw new Error('argument is not a function')
}
return source.lift(new MapOperator(project));
}
}
原理解析:
1、当调用Observable当map操作时,执行Observable的lift方法创建一个新的Observable,并将当前的Observable作为其source,map作为其operator
2、当调用subscribe方法时,判断当前Observable是否存在operator,很显然我们当前的operator时map,所以执行map操作的call方法
3、在call方法中会调用source的subscribe方法,并将mapSubscribe作为observer
4、subscribe方法中再次判断是否有observable,显然source是没有operator的,所以就执行Observable.create传递的回调方法
5、执行next方法的时候,会先执行mapSubscribe的next方法,然后调用创建时observer的next方法。也就是
mapSubscribe.next(observer.next)层层传递。