最近对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微信公众号
期待后续内容!
下午在看angular2,正好碰到rx的报错,搜到这里,感谢克君老师
克军大大又走在了前列线 =。=
写的什么破玩意。概念没搞清,用法也不对。
共收到4条回复