发布于 2016-01-15 00:05:09 | 610 次阅读 | 评论: 0 | 来源: PHPERZ
RxJS JavaScript 的 Reactive 扩展
静态网页已经成为历史,如今的web设计趋势是预测客户想法并提供更好的互动功能,例如自动填写表单、搜索Wikipedia等。RxJS框架可以很方便地为鼠标和键盘事件提供响应。
前几天在seg里发布了一篇RxJS的介绍和教程,几天的系统推送提醒说明大家对这个主题很是很感兴趣的,详见RxJS介绍。
Rx 是一种编程的思维,而不是一个特定的框架和库。我决定,今后写一系列“深入浅出”的文章来介绍 Rx。我选择RxJS作为base,所有的代码实例都会基于RxJS,这一系列文章主要会涉及以下几个方面:
我对Rx编程的理解,和自己使用中的感悟
对Rx*标准:对象、方法(API)的阐述
后面想到再补充
这个系列,会坚持原创和国外优秀教程的翻译。API部分绝对不会仅仅是API的翻译,我相信这个部分更有意思。当然这是个浩大的工程,希望我可以完成。
注:Object.method为对象方法,Object#method为实例方法
[Rx.Observable.amb(...args)
]
args
(Array|arguments):方法参数为多个可观察对象(流),或者是Promise对象,对象间存在竞争关系。
(Observable
) :方法返回呈竞争态的多个流中,首先相应的流。
简单的说,amb()
像一个多路电闸,一次仅能联通一条通路:
| | | | | | | |
A B C D E F G H
| | | | | | | |
\
\ 开关臂
\
|
主线
|
函数需要做出 选择 ,选择的依据就是哪一个可观察对象(流)先发射了值。选择后,仅有“联通”的流会被观察到,下面这个图会形象一下,还是用 电路 做比喻,其中“ * ”表示电子:
*
| | | | | | |
*
| | | | | | |
A B C D E F G
| | | | | | |
*
| | | | | | |
*
| | | | | | |
*
⊗
可以看到,E支流的电子先到达了末端,所以E路被接通,并且对外界而言,所有订阅者观察的对象看,就是这个联通了E支流。
Rx官方喜欢使用珠宝图来表示各个函数的作用,珠宝图表示amb()
。
我来介绍一下牛逼的 珠宝图 :
从左到右的箭头,代表时间轴。|
代表可观察对象(流)发出了完成信号。
轴上的每一个珠宝代表流发射的值;
下方amd
那个层是处理操作符,本图意味着所有操作符上的流,都会经过操作符的处理;
最下方是,操作符处理后的输出结果。y = f(x)
,其中x
表示输入流,f()
是操作符,y
是最后的输出流。
观察上面的珠宝图,1, 2, 3
这个流最先发射了值,所以amb()
选择了它,作为了最终的输出。如果这个流被观察者订阅,订阅者会依次收到1
,
2
和 3
。
当然,珠宝图不是静态的摆设 !珠宝图不是静态的摆设 !珠宝图不是静态的摆设!
我们可以拖动上面的每一个珠宝,来改变流中事件的发生顺序:
我们拖动第一个流——20, 40, 60
,把20
这个珠宝拖到所有的珠宝前面。按照amb()
的原理,我们可以推断,输出流会变为20, 40, 60
。截图验证一下:
最后补充一点:当一个流被联通后,其他的流肿么办?现在先记住结论:未被选择的流奖杯调用dispose方法,也就是说,他们被关闭了。
HTML
<body>
<input id="input1" type="text">
<input id="input2" type="text">
</body>
JavaScript
input1 = $('#input1');
input2 = $('#input2');
var source = Rx.Observable.amb(
Rx.Observable.fromEvent(input1, 'click')
.map(()=>'one'),
Rx.Observable.fromEvent(input2, 'click')
.map(()=>'two')
);
上面例子中,amb()
中传入了两个点击事件流。事件流1,会在点击后发射字符串“one”;事件流2,会在点击后发射字符串“two”;
初始情况下,产生事件流1之后,事件流2不会再被输出;反之亦然,我们可以订阅amb()
产生的结果流:
var subscription = source.subscribe(
function (x) {
console.log(x);
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});
具体可演示实例,可以进入amb数演示
。订阅结果会在控制台中输出。你可以在充分理解了amb()
的原理之后修改可演示的实例,来验证自己的掌握程度。
上文提到过 Rx 是一套模式,各个平台、语言都有对模式的实现。
我们试着探讨下amb()
更宽泛地应用:
秒杀系统 :秒杀是一个高并发的场景,出现“多卖”是常态,“多卖”是由于秒杀商品的库存问题引起的。参与秒杀的用户呈竞争态,将请求分组后(比如100个一组),通过amd()
可以甄选出具有购买资格的用户:因为秒杀的产品逻辑是:谁手快,谁买到。
Observable.amb(
用户A的拍下请求,
用户B的拍下请求,
用户C的拍下请求,
...
).subscribe(function(user) {
执行购买逻辑,创建订单,打开支付工具
})
你的移动电话:假设同一时间多个人呼叫你,你接通了最先到达的A的来电,这段时间内你就只能和A通话了,其余呼叫将会接收到忙音。
Observable.amb(
A来电,
B来电,
C来电,
...
).subscribe(function(call) {
通话吧啦吧啦
})
剧终