[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 ...
随机推荐
- Git 修复 bug 切换分支时,如何保存修改过的代码(即如何保存现场)?
工作除了开发最新的版本之外还要对原来的版本做例行的维护,修修补补.于是有了在两个分支之间游走切换的问题,最新改版的代码在分支 new 上,旧版本的代码在分支 old 上,我在 new 上开发了一半,忽 ...
- Weekly linux and ConferenceByYear(2002-now)
https://lwn.net/Archives/ https://lwn.net/Archives/ConferenceByYear/
- .Net 垃圾回收和大对象处理 内存碎片整理
CLR垃圾回收器根据所占空间大小划分对象.大对象和小对象的处理方式有很大区别.比如内存碎片整理 —— 在内存中移动大对象的成本是昂贵的,让我们研究一下垃圾回收器是如何处理大对象的,大对象对程序性能有哪 ...
- c编程:输入一个数字n,则n代表n行,每行输入2个数字a,b计算每行的a+b问题。
输入 第一行输入要计算的数据组数 n 接下来的 n 行,每行包括两个数a和b 输出 每行输出一组数据中a+b的值 例子输入 2 1 2 4 0 例子输出 3 4 代码: #include<std ...
- JavaScript进阶系列02,函数作为参数以及在数组中的应用
有时候,把函数作为参数可以让代码更简洁. var calculator = { calculate: function(x, y, fn) { return fn(x, y); } }; var su ...
- Java异常(三) 《Java Puzzles》中关于异常的几个谜题
概要 本章介绍<Java Puzzles>中关于异常的几个谜题.这一章都是以代码为例,相比上一章看起来更有意思.内容包括:谜题1: 优柔寡断谜题2: 极端不可思议谜题3: 不受欢迎的宾客谜 ...
- C#编程(五十六)----------可观察的集合ObservableCollection
原文链接: http://blog.csdn.net/shanyongxu/article/details/47080685 可观察的集合 如果需要集合中的元素核实删除或添加的信息,就可以使用Obse ...
- VirtualBox - NAT虚拟机访问外网 + Host-Only物理主机虚拟机互访
[root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-System_eth0 # 未手动设定HOST-ONLY静态IP时的默认值 #T ...
- ibatis.net:第一天,什么是 mybatis.net ?
ibatis.net 是一个“数据映射框架”,它使得面向对应的应用程序非常的方面使用关系数据.ibatis.net 通过使用 xml 或 attribute 来解耦对象和SQL或存储过程.简单是 ib ...
- Linux线程优先级
转自:https://www.cnblogs.com/imapla/p/4234258.html Linux内核的三种调度策略: 1.SCHED_OTHER 分时调度策略 2.SCHED_FIFO ...