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:

  1. import { from } from "rxjs";
  2. import { map, filter } from "rxjs/operators";
  3.  
  4. from([, , , ])
  5. .pipe(map(x => x * ))
  6. .pipe(filter(x => x < ))
  7. .subscribe(val => console.log(val));
  8. // 2
  9. //

We can build our own RxJS operator

First, Observable,

  it has API:

  1. {
  2. subscribe() {}
  3. pipe() {}
  4. }

We can create a function call 'createObservable(subscribe)', take a subscribe function, return a subscribe and pipe function:

  1. function createObservable(subscribe) {
  2. return {
  3. subscribe,
  4. pipe(operator) {
  5. return operator(this);
  6. }
  7. };
  8. }

We can use it to create Observables:

  1. const numberObservable = createObservable(function(observer) {
  2. [, , , ].forEach(x => {
  3. observer.next(x);
  4. });
  5.  
  6. observer.complete();
  7. });
  8.  
  9. const clickObservable = createObservable(function(observer) {
  10. document.addEventListener("click", function(ev) {
  11. observer.next(ev);
  12. });
  13. });

Second, Observer:

  Observer is easy, it takes a object which contains 'next', 'error', 'complete' functions:

  1. const observer = {
  2. next(x) {
  3. console.log(x);
  4. },
  5. error(err) {
  6. console.error(err);
  7. },
  8. complete() {
  9. console.log("DONE");
  10. }
  11. };

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.

  1. const map = fn => inputObservable => {
  2. const outputObservable = createObservable(function(outputObserver) {
  3. const observer = {
  4. next(x) {
  5. const res = fn(x);
  6. outputObserver.next(res);
  7. },
  8. error(err) {
  9. outputObserver.error(err);
  10. },
  11. complete() {
  12. outputObserver.complete();
  13. }
  14. };
  15. inputObservable.subscribe(observer);
  16. });
  17.  
  18. return outputObservable;
  19. };
  20.  
  21. const filter = fn => inputObservable => {
  22. const outputObservable = createObservable(function(outputObserver) {
  23. const observer = {
  24. next(x) {
  25. if (fn(x)) {
  26. outputObserver.next(x);
  27. }
  28. },
  29. error(err) {
  30. outputObserver.error(err);
  31. },
  32. complete() {
  33. outputObserver.complete();
  34. }
  35. };
  36. inputObservable.subscribe(observer);
  37. });
  38.  
  39. return outputObservable;
  40. };

--

Full Code:

  1. function createObservable(subscribe) {
  2. return {
  3. subscribe,
  4. pipe(operator) {
  5. return operator(this);
  6. }
  7. };
  8. }
  9.  
  10. const numberObservable = createObservable(function(observer) {
  11. [, , , ].forEach(x => {
  12. observer.next(x);
  13. });
  14.  
  15. observer.complete();
  16. });
  17.  
  18. const clickObservable = createObservable(function(observer) {
  19. document.addEventListener("click", function(ev) {
  20. observer.next(ev);
  21. });
  22. });
  23.  
  24. const map = fn => inputObservable => {
  25. const outputObservable = createObservable(function(outputObserver) {
  26. const observer = {
  27. next(x) {
  28. const res = fn(x);
  29. outputObserver.next(res);
  30. },
  31. error(err) {
  32. outputObserver.error(err);
  33. },
  34. complete() {
  35. outputObserver.complete();
  36. }
  37. };
  38. inputObservable.subscribe(observer);
  39. });
  40.  
  41. return outputObservable;
  42. };
  43.  
  44. const filter = fn => inputObservable => {
  45. const outputObservable = createObservable(function(outputObserver) {
  46. const observer = {
  47. next(x) {
  48. if (fn(x)) {
  49. outputObserver.next(x);
  50. }
  51. },
  52. error(err) {
  53. outputObserver.error(err);
  54. },
  55. complete() {
  56. outputObserver.complete();
  57. }
  58. };
  59. inputObservable.subscribe(observer);
  60. });
  61.  
  62. return outputObservable;
  63. };
  64.  
  65. const observer = {
  66. next(x) {
  67. console.log(x);
  68. },
  69. error(err) {
  70. console.error(err);
  71. },
  72. complete() {
  73. console.log("DONE");
  74. }
  75. };
  76.  
  77. numberObservable
  78. .pipe(map(x => x * ))
  79. .pipe(map(x => x - ))
  80. .subscribe(observer);
  81.  
  82. clickObservable
  83. .pipe(map(ev => [ev.clientX, ev.clientY]))
  84. .pipe(filter(([x, y]) => x < && y < ))
  85. .subscribe(observer);

[RxJS] Build your own RxJS的更多相关文章

  1. RxJS入门2之Rxjs的安装

    RxJS V6.0+ 安装 RxJS 的 import 路径有以下 5 种: 1.创建 Observable 的方法.types.schedulers 和一些工具方法 import { Observa ...

  2. [rxjs] Throttled Buffering in RxJS (debounce)

    Capturing every event can get chatty. Batching events with a throttled buffer in RxJS lets you captu ...

  3. [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 ...

  4. [RxJS] Combining streams in RxJS

    Source: Link We will looking some opreators for combining stream in RxJS: merge combineLatest withLa ...

  5. [RxJS] Error Handling in RxJS

    Get your code back on the happy path! This lesson covers a variety of ways to handle exceptions thro ...

  6. [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 ...

  7. rxjs入门4之rxjs模式设计

    观察者模式 (Observer Pattern) 观察者模式其实在日常编码中经常遇到,比如DOM的事件监听,代码如下 function clickHandler(event) { console.lo ...

  8. angular2 学习笔记 ( Rxjs, Promise, Async/Await 的区别 )

    Promise 是 ES 6 Async/Await 是 ES 7 Rxjs 是一个 js 库 在使用 angular 时,你会经常看见这 3 个东西. 它们都和异步编程有关,有些情况下你会觉得用它们 ...

  9. [转]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 ...

随机推荐

  1. Git 修复 bug 切换分支时,如何保存修改过的代码(即如何保存现场)?

    工作除了开发最新的版本之外还要对原来的版本做例行的维护,修修补补.于是有了在两个分支之间游走切换的问题,最新改版的代码在分支 new 上,旧版本的代码在分支 old 上,我在 new 上开发了一半,忽 ...

  2. Weekly linux and ConferenceByYear(2002-now)

    https://lwn.net/Archives/ https://lwn.net/Archives/ConferenceByYear/

  3. .Net 垃圾回收和大对象处理 内存碎片整理

    CLR垃圾回收器根据所占空间大小划分对象.大对象和小对象的处理方式有很大区别.比如内存碎片整理 —— 在内存中移动大对象的成本是昂贵的,让我们研究一下垃圾回收器是如何处理大对象的,大对象对程序性能有哪 ...

  4. c编程:输入一个数字n,则n代表n行,每行输入2个数字a,b计算每行的a+b问题。

    输入 第一行输入要计算的数据组数 n 接下来的 n 行,每行包括两个数a和b 输出 每行输出一组数据中a+b的值 例子输入 2 1 2 4 0 例子输出 3 4 代码: #include<std ...

  5. JavaScript进阶系列02,函数作为参数以及在数组中的应用

    有时候,把函数作为参数可以让代码更简洁. var calculator = { calculate: function(x, y, fn) { return fn(x, y); } }; var su ...

  6. Java异常(三) 《Java Puzzles》中关于异常的几个谜题

    概要 本章介绍<Java Puzzles>中关于异常的几个谜题.这一章都是以代码为例,相比上一章看起来更有意思.内容包括:谜题1: 优柔寡断谜题2: 极端不可思议谜题3: 不受欢迎的宾客谜 ...

  7. C#编程(五十六)----------可观察的集合ObservableCollection

    原文链接: http://blog.csdn.net/shanyongxu/article/details/47080685 可观察的集合 如果需要集合中的元素核实删除或添加的信息,就可以使用Obse ...

  8. VirtualBox - NAT虚拟机访问外网 + Host-Only物理主机虚拟机互访

    [root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-System_eth0 # 未手动设定HOST-ONLY静态IP时的默认值 #T ...

  9. ibatis.net:第一天,什么是 mybatis.net ?

    ibatis.net 是一个“数据映射框架”,它使得面向对应的应用程序非常的方面使用关系数据.ibatis.net 通过使用 xml 或 attribute 来解耦对象和SQL或存储过程.简单是 ib ...

  10. Linux线程优先级

    转自:https://www.cnblogs.com/imapla/p/4234258.html Linux内核的三种调度策略: 1.SCHED_OTHER 分时调度策略 2.SCHED_FIFO   ...