w3ctech

RxJS初体验

最近对FRP感兴趣,在项目中用了用RxJS,分享一下并不深刻的感受。RxJS全名Reactive Extensions for JavaScript,Javascript的响应式扩展。响应式的思路是把随时间不断变化的数据、状态、事件等等转成可被观察的序列(Observable Sequence),然后订阅序列中那些Observable对象的变化,一旦变化,就会执行事先安排好的各种转换和操作。RxJS作为一个库,可以和任何框架混用,如果想体验一下函数响应式编程的奇妙之处不妨一用。

适用场景:1.异步操作重,2.同时处理多个数据源。

先比较一下Promise。在项目中经常会遇到组装接囗的问题,想要的数据来自多个数据源,而且有依赖关系,比如data3是通过data2的id取到的,data1和data2来自不同的接囗。如果用Promise是这样实现的(为了简洁都用ES6写):

var reqData1 = url => new Promise((resolve, reject) => setTimeout(() => resolve(42), 1000));
var reqData2 = url => new Promise((resolve, reject) => setTimeout(() => resolve(52), 500));
var reqData3 = (url,params) => new Promise((resolve, reject) => setTimeout(() => resolve(62), 800));

Promise.all([reqData1(api_1), reqData2(api_2)])
       .then((data1, data2) => {
         return reqData3(api_3, {id: data2.id}).then(data3 => {
          data1: data1,
          data2: data2,
          data3: data3,
        });
       })
       .then(data => {
         initComponent(data);
       });

RxJS的实现是这样的:

var reqData1 = (url, cb) => setTimeout(() => cb(42), 1000));
var reqData2 = (url, cb) => setTimeout(() => cb(52), 500));
var reqData3 = (url, params, cb) => setTimeout(() => cb(62), 800));

var dataReq1 = new Rx.Subject();
var dataReq2 = new Rx.Subject();
Rx.Observable.when(dataReq1.and(dataReq2).thenDo((data1, data2) => {
  return {
    data1: data1,
    data2: data2
  }
}))
.flatMap(data => {
  var s = new Rx.Subject()
  reqData3(api_3, { id: e.data2.id }, e => {
    data.data3 = e;
    s.onNext(data);
    s.onCompleted();
  });
  return s;
})
.subscribe( data => {
  initComponent(data);
});
reqData1(api_1, (e) => dataReq1.onNext(e));
reqData2(api_2, (e) => dataReq2.onNext(e));

Winter在《用Promise组织程序》一文中,举过一个FRP范式的例子,实现点button或5秒后执行某个操作:

function wait(duration){
    return new Promise(function(resolve, reject) {
        setTimeout(resolve,duration);
    })
}

function waitFor(element,event,useCapture){
    return new Promise(function(resolve, reject) {
        element.addEventListener(event,function listener(event){
            resolve(event)
            this.removeEventListener(event, listener, useCapture);
        },useCapture)
    })
}

var btn = document.getElementById('button');
Promise.race(wait(5000), waitFor(btn, click)).then(function(){
    console.log('run!')
})

RxJS的实现很简洁:

var btn = document.getElementById('button');
var logRun = Rx.Observable.fromEvent(btn, 'click')
             .merge(Rx.Observable.timer(3000))
             .subscribe(e => {
               console.log('run!');
               logRun.dispose(); // 如果是一次性的就移除observable
             });

从上述的例子中体会一下RxJS的基本用法。Rx.Observable.*创建一个Observable对象,当它发生变化时,以流式的方式触发各种转换(如有需要可以对变化的值做合并、映射、过滤等操作),最后传到订阅回调拿到处理后的最终结果。

先告一段落,以后再陆续补充。

w3ctech微信

扫码关注w3ctech微信公众号

共收到4条回复

  • 期待后续内容!

    回复此楼
  • 下午在看angular2,正好碰到rx的报错,搜到这里,感谢克君老师

    回复此楼
  • 克军大大又走在了前列线 =。=

    回复此楼
  • 写的什么破玩意。概念没搞清,用法也不对。

    回复此楼