前言 偶然看到隔壁的小伙伴在用 RxJS,他说这是一款不错的 处理异步事件流 一个工具,对于 RxJS 的认识,也就是只听说过一个名词而已,对于具体处理什么 业务场景确实不得而知了.故此花了一定的时间来入门了解一下.
响应式编程 RxJS 是针对响应式编程 实现的一个库,什么是响应式编程?它与面向对象 ,命令式编程  地位与之并列,是一种利用异步事件流的 方式进行编程, 具体长什么样的,先来一段 JS 代码来看看
1 2 3 4 5 6 7 8 9 10 const  { Observable  } = rxjs;const  stringStream = new  Observable (function  (subscriber ) {   subscriber.next ("hello world" ); }); stringStream.subscribe ({   next : (data ) =>  {     console .log (data);    }, });
 
这就好像 一般的 Event Bus  或者看着像 Promise ,不错,你可以认为这是他们的升级版,但这样看不出写的好处在哪,反而有一点繁琐. 是的,单凭上面小小的例子看不出什么门道,但里面却贯穿着一个无比重要的思想 everything is stream 
everything is stream 响应式编程的魔咒,从现在开始,我们要抛弃命令式的思维 去编写程序,重新从另一个角度去看待事件.everything is stream ,一切皆是流,怎么理解这就话,页面的点击,用户的输入,请求的过程,编程的一切都从流开始,用户的输入的字符串就是一个流,这个流(所带的数据)可以被更改,删除,替换,在一定的阶段,我们可以(消费)获取到这个流来做一些事情.下面给出几个简单的例子加深一下理解
监听用户的点击按钮,并获取按钮上的 id 值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const  { fromEvent } = rxjs;const  { map } = rxjs.operators ;const  btnDom = document .querySelector ("#btn" );const  buttonClickStream = fromEvent (btnDom, "click" ); buttonClickStream.subscribe ((event ) =>  {   console .log (event); }); buttonClickStream.pipe (map ((event ) =>  event.target .id )).subscribe ((value ) =>  {   console .log (value);  });
 
对输入框进行防抖处理 1 2 3 4 5 6 7 8 9 10 11 const  { fromEvent } = rxjs;const  { debounceTime } = rxjs.operators ;const  searchInputDom = document .querySelector ("#searchInput" );fromEvent (searchInputDom, "change" )   .pipe (debounceTime (1000 ))   .subscribe ((e ) =>  {     console .log (e.target .value );    });
 
小结 从上面连个小例子不难看出,我们编程首先要切换到 “流式思想” ,然后对这个流进行各种处理,得到我们想到的 值,最后我们消费该值,当然,转换流式思想有一定的难度,这就需要在项目中不断的实践,还要经常去查看 RxJS 提供的操作符,如何优雅辨别流之间的关系,以及组合,这是后续学习的一个难点.说这这么久,还没说它到底有什么业务场景需要使用,使用不多,我只能从网上摘出几点
让异步编程以同步的方式编写 
加深代码抽象的程度,让你可以更专注于定义与事件相互依赖的业务逻辑,而不是把大量精力放在实现细节上,同时,使用响应式编程还能让你的代码变得更加简洁 
 
学习成本还是很高的,但就目前而言,大多数场景都用不上,但开拓思维还是不错的
一个完成的登陆例子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 <!DOCTYPE html > <html  lang ="en" >    <head >      <meta  charset ="UTF-8"  />      <meta  name ="viewport"  content ="width=device-width, initial-scale=1.0"  />      <title > Document</title >      <script  src ="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js" > </script >    </head >    <body >      <div  id ="btn" > 点击一下按钮</div >      <form  id ="form" >        <div >          <input  placeholder ="xxxx"  id ="phone"  />          <div  style ="color: red;"  id ="error" > </div >        </div >        <input  type ="password"  id ="password"  />        <input  type ="submit"  id ="submitBtn"  />      </form >      <script >       window .onload  = function  ( ) {         const  { range, fromEvent, Observable , from , of , interval } = rxjs;         const  {           map,           filter,           scan,           throttle,           debounceTime,           flatMap,         } = rxjs.operators ;         const  query = document .querySelector ;         const  phoneDom = query ("#phone" );         const  passwordDom = query ("#password" );         const  errorDom = query ("#error" );         const  submitBtn = query ("#submitBtn" );         const  form = query ("#form" );         const  passwordStream = fromEvent (passwordDom, "change" );         passwordStream.subscribe ((e ) =>  {           console .log (e.target .value );         });         const  checkPhoneBlurStream = fromEvent (phoneDom, "blur" );         const  checkPhone  = (value ) =>           /0?(13|14|15|18|17)[0-9]{9}/g .test (value) && value.length  === 11 ;         checkPhoneBlurStream           .pipe (map ((event ) =>  checkPhone (event.target .value )))           .subscribe ((value ) =>  {             if  (!value) {               errorDom.innerHTML  = "请输入合法的字符" ;             } else  {               errorDom.innerHTML  = "" ;             }           });         const  formStream = fromEvent (form, "submit" );         formStream           .pipe (             map ((event ) =>  {               event.preventDefault ();               if  (checkPhone (phoneDom.value )) {                 return  {                   phone : phoneDom.value ,                   password : phoneDom.password ,                 };               }               return  null ;             }),             filter ((value ) =>  value !== null )           )           .subscribe ((data ) =>  {             loginStream (data);           });         const  loginApi = function  (data ) {           return  new  Promise (function  (resolve, reject ) {             setTimeout (function  ( ) {               resolve ([{ success : "成功" , data : data }]);             }, 2000 );           });         };         function  loginStream (data ) {           const  loginDataStream = of (data);           loginDataStream             .pipe (flatMap ((data ) =>  from (loginApi (data))))             .subscribe ((value ) =>  {               console .log (value);             });         }       };      </script >    </body > </html > 
 
参考链接: https://rxjs.dev/ 
https://github.com/benjycui/introrx-chinese-edition 
https://hijiangtao.github.io/2020/01/13/RxJS-Introduction-and-Actions/