[RxJS] Write Subject & Share operator
class Observable {
constructor(subscribe) {
this._subscribe = subscribe;
}
subscribe(observer) {
return this._subscribe(observer);
}
static concnat(...observables) {
return new Observable((observer) => {
const copy = observables.slice();
let currentSubscription = null;
// using recurisve call to implement concat effect
// for each call, there we update currentSubscription
// when calling unsubscribe on currentSubscription
// complete() won't be triggered, therefore whole
// observables stops as well
const processObservable = () => {
if (!copy.length) {
observer.complete();
} else {
const observable = copy.shift();
currentSubscription = observable.subscribe({
next(data) {
observer.next(data);
},
error(err) {
observer.error(err);
currentSubscription.unsubscribe();
},
complete() {
processObservable();
}
});
}
};
processObservable();
return {
unsubscribe: () => {
currentSubscription.unsubscribe();
}
};
});
}
static timeout(time) {
return new Observable((observer) => {
console.log("CALL TIMEOUT");
const handle = setTimeout(() => {
observer.next();
observer.complete();
}, time);
return {
unsubscribe: () => {
clearTimeout(handle);
}
};
});
}
static fromEvent(dom, eventName) {
return new Observable((observer) => {
const handle = (e) => {
observer.next(e);
};
dom.addEventListener(eventName, handle);
return {
unsubscribe: () => {
dom.removeEventListener(eventName, handle);
}
};
});
}
retry(num) {
return new Observable((observer) => {
let currentSub;
const retry = (currentAmttemptNumber) => {
currentSub = this.subscribe({
next(data) {
observer.next(data);
},
error(err) {
if (currentAmttemptNumber === 0) {
observer.error(err);
} else {
retry(currentAmttemptNumber - 1);
}
},
complete() {
observer.complete();
}
});
};
retry(num);
return {
unsubscribe() {
if (currentSub) {
currentSub.unsubscribe();
}
}
};
});
}
// map is a operator, you need to subscribe it
map(transfomer) {
return new Observable((observer) => {
const subscription = this.subscribe({
next(data) {
let value;
try {
value = transfomer(data);
observer.next(value);
} catch (err) {
observer.error(err);
subscription.unsubscribe();
}
},
error(e) {
observer.error(e);
},
complete() {
observer.complete();
}
});
return subscription;
});
}
filter(predition) {
return new Observable((observer) => {
const subscription = this.subscribe({
next(data) {
try {
if (predition(data)) {
observer.next(data);
}
} catch (err) {
observer.error(err);
subscription.unsubscribe();
}
},
error(e) {
observer.error(e);
},
complete() {
observer.complete();
}
});
return subscription;
});
}
share() {
const subject = new Subject();
this.subscribe(subject);
return subject;
}
}
class Subject extends Observable {
constructor() {
super((observer) => {
this.observers.add(observer);
return {
unsubscribe() {
this.observers.delete(observer);
}
};
});
this.observers = new Set();
}
next(v) {
for (let observer of [...this.observers]) {
observer.next(v);
}
}
error(e) {
for (let observer of [...this.observers]) {
observer.next(e);
}
}
complete() {
for (let observer of [...this.observers]) {
observer.complete();
}
}
}
const button = document.getElementById("btn");
const buttonClick = Observable.fromEvent(button, "click");
const buttonClickOffset = buttonClick.map((pointerEvent) => {
return {
offsetX: pointerEvent.offsetX,
offsetY: pointerEvent.offsetY
};
});
const buttonClickOffsetRight = buttonClickOffset.filter((ev) => {
return ev.offsetX > 40;
});
buttonClickOffsetRight.subscribe({
next(e) {
console.log(e);
},
error(e) {
console.error(e);
},
complete() {
console.log("completed");
}
});
const timeout = Observable.timeout(500).share();
timeout.subscribe({
next(v) {
console.log(v);
},
error(e) {
console.error(e);
},
complete() {
console.log("completed");
}
});
timeout.subscribe({
next(v) {
console.log(v);
},
error(e) {
console.error(e);
},
complete() {
console.log("completed");
}
});
分类:
Javascript
, RxJS
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2022-09-12 [Typescript Challenges] 28. Medium - Replace
2022-09-12 [Typescript] 27. Medium - Capitalize
2022-09-12 [Go] Slice vs Array creation
2018-09-12 [Javascript] Flattening nested arrays: a little exercise in functional refactoring
2017-09-12 [Vue + TS] Create Type-Safe Vue Directives in TypeScript
2016-09-12 [Javascript] Monads
2016-09-12 [Javascript] Functor law