[RxJS] Build your own RxJS
JavaScript has multiple APIs that use callback functions that all do nearly the same thing with slight variations. Event listeners, array methods such as .forEach, promises, and NodeJS streams all are very close in the way they are written. Instead, in RxJS you'd unify all of these APIs under one abstraction.
Normal RxJS API:
import { from } from "rxjs";
import { map, filter } from "rxjs/operators";
from([, , , ])
.pipe(map(x => x * ))
.pipe(filter(x => x < ))
.subscribe(val => console.log(val));
// 2
//
We can build our own RxJS operator
First, Observable,
it has API:
{
subscribe() {}
pipe() {}
}
We can create a function call 'createObservable(subscribe)', take a subscribe function, return a subscribe and pipe function:
function createObservable(subscribe) {
return {
subscribe,
pipe(operator) {
return operator(this);
}
};
}
We can use it to create Observables:
const numberObservable = createObservable(function(observer) {
[, , , ].forEach(x => {
observer.next(x);
});
observer.complete();
});
const clickObservable = createObservable(function(observer) {
document.addEventListener("click", function(ev) {
observer.next(ev);
});
});
Second, Observer:
Observer is easy, it takes a object which contains 'next', 'error', 'complete' functions:
const observer = {
next(x) {
console.log(x);
},
error(err) {
console.error(err);
},
complete() {
console.log("DONE");
}
};
Third, Operator, map, filter:
map(fn)(observable)
filter(predFn)(observable)
It is important to know that map & filter, those operator, takes an inputObservable and will return an outputObservable.
We subscribe inputObservable, and inputObserver, inside inputObserver, we call outputObserver which is passed in from the consumer.
const map = fn => inputObservable => {
const outputObservable = createObservable(function(outputObserver) {
const observer = {
next(x) {
const res = fn(x);
outputObserver.next(res);
},
error(err) {
outputObserver.error(err);
},
complete() {
outputObserver.complete();
}
};
inputObservable.subscribe(observer);
});
return outputObservable;
};
const filter = fn => inputObservable => {
const outputObservable = createObservable(function(outputObserver) {
const observer = {
next(x) {
if (fn(x)) {
outputObserver.next(x);
}
},
error(err) {
outputObserver.error(err);
},
complete() {
outputObserver.complete();
}
};
inputObservable.subscribe(observer);
});
return outputObservable;
};
--
Full Code:
function createObservable(subscribe) {
return {
subscribe,
pipe(operator) {
return operator(this);
}
};
}
const numberObservable = createObservable(function(observer) {
[, , , ].forEach(x => {
observer.next(x);
});
observer.complete();
});
const clickObservable = createObservable(function(observer) {
document.addEventListener("click", function(ev) {
observer.next(ev);
});
});
const map = fn => inputObservable => {
const outputObservable = createObservable(function(outputObserver) {
const observer = {
next(x) {
const res = fn(x);
outputObserver.next(res);
},
error(err) {
outputObserver.error(err);
},
complete() {
outputObserver.complete();
}
};
inputObservable.subscribe(observer);
});
return outputObservable;
};
const filter = fn => inputObservable => {
const outputObservable = createObservable(function(outputObserver) {
const observer = {
next(x) {
if (fn(x)) {
outputObserver.next(x);
}
},
error(err) {
outputObserver.error(err);
},
complete() {
outputObserver.complete();
}
};
inputObservable.subscribe(observer);
});
return outputObservable;
};
const observer = {
next(x) {
console.log(x);
},
error(err) {
console.error(err);
},
complete() {
console.log("DONE");
}
};
numberObservable
.pipe(map(x => x * ))
.pipe(map(x => x - ))
.subscribe(observer);
clickObservable
.pipe(map(ev => [ev.clientX, ev.clientY]))
.pipe(filter(([x, y]) => x < && y < ))
.subscribe(observer);
[RxJS] Build your own RxJS的更多相关文章
- RxJS入门2之Rxjs的安装
RxJS V6.0+ 安装 RxJS 的 import 路径有以下 5 种: 1.创建 Observable 的方法.types.schedulers 和一些工具方法 import { Observa ...
- [rxjs] Throttled Buffering in RxJS (debounce)
Capturing every event can get chatty. Batching events with a throttled buffer in RxJS lets you captu ...
- [RxJS] Stream Processing With RxJS vs Array Higher-Order Functions
Higher order Array functions such as filter, map and reduce are great for functional programming, bu ...
- [RxJS] Combining streams in RxJS
Source: Link We will looking some opreators for combining stream in RxJS: merge combineLatest withLa ...
- [RxJS] Error Handling in RxJS
Get your code back on the happy path! This lesson covers a variety of ways to handle exceptions thro ...
- [RxJS 6] The Retry RxJs Error Handling Strategy
When we want to handle error observable in RxJS v6+, we can use 'retryWhen' and 'delayWhen': const c ...
- rxjs入门4之rxjs模式设计
观察者模式 (Observer Pattern) 观察者模式其实在日常编码中经常遇到,比如DOM的事件监听,代码如下 function clickHandler(event) { console.lo ...
- angular2 学习笔记 ( Rxjs, Promise, Async/Await 的区别 )
Promise 是 ES 6 Async/Await 是 ES 7 Rxjs 是一个 js 库 在使用 angular 时,你会经常看见这 3 个东西. 它们都和异步编程有关,有些情况下你会觉得用它们 ...
- [转]VS Code 扩展 Angular 6 Snippets - TypeScript, Html, Angular Material, ngRx, RxJS & Flex Layout
本文转自:https://marketplace.visualstudio.com/items?itemName=Mikael.Angular-BeastCode VSCode Angular Typ ...
随机推荐
- STM32 GPIO 配置之ODR, BSRR, BRR 详解
STM32 GPIO 配置之ODR, BSRR, BRR 详解 用stm32 的配置GPIO 来控制LED 显示状态,可用ODR,BSRR,BRR 直接来控制引脚输出状态. ODR寄存器可读可写:既能 ...
- TCPIP网络协议层对应的RFC文档
原文地址:TCPIP网络协议层对应的RFC文档作者:西木 RFC - Request For Comments 请求注解 TCP/IP层 网络协议 RFC文档 Physical Layer Data ...
- Revit MEP API找到连接器连接的连接器
通过conn.AllRefs;可以找到与之连接的连接器. //连接器连接的连接器 [TransactionAttribute(Autodesk.Revit.Attributes.Transaction ...
- 搭建《深入Linux内核架构》的Linux环境
作者 彭东林 pengdonglin137@163.com 软件 Host: Ubuntu14.04 64 Qemu 2.8.0 Linux 2.6.24 busybox 1.24.2 gcc 4.4 ...
- Task Parallel Library01,基本用法
我们知道,每个应用程序就是一个进程,一个进程有多个线程.Task Parallel Library为我们的异步编程.多线程编程提供了强有力的支持,它允许一个主线程运行的同时,另外的一些线程或Task也 ...
- iPhone/iPad各种文件路径详解 帮助了解自己的iphone和ipad
以下内容皆为转载分享iPhone里重要的目录路径有哪几个? 1. /private/var/mobile 新刷完的机器,要在这个文件夹下建一个Documents的目录,很多程序都要用到. 2. /pr ...
- 【tensorflow】1.安装Tensorflow开发环境,安装Python 的IDE--PyCharm
================================================== 安装Tensorflow开发环境,安装Python 的IDE--PyCharm 1.PyCharm ...
- Android之TextView部分颜色变动
public class StringHandleExampleActivity extends Activity { /** Called when the activity is first cr ...
- Android 代码实现应用强制装到手机内存
在Froyo(android 2.2,API Level:8)中引入了android:installLocation.通过设置该属性可以使得开发者以及用户决定程序的安装位置. android:inst ...
- Java并发编程的艺术(十二)——线程安全
1. 什么是『线程安全』? 如果一个对象构造完成后,调用者无需额外的操作,就可以在多线程环境下随意地使用,并且不发生错误,那么这个对象就是线程安全的. 2. 线程安全的几种程度 线程安全性的前提:对『 ...