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的报错,搜到这里,感谢克君老师

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

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

    回复此楼

AltStyle によって変換されたページ (->オリジナル) /