*不是我没学,我只是懒得不想把Raw笔记转码了而已。~~懒得要死~~
注:本文学习环境为RxJs5.x版本,目前使用环境为RxJs6,故部分声明代码不同
例如:大部分operator将不需要前置的Rx.Observable,直接调用即可。
分割线-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Observable可以同时处理同步与异步传来的信息
var observable = Rx.Observable // 1.创建一个observable对象,新版应改为直接使用Observable?
.create(function(observer) {
observer.next('Jerry'); // 同步部分
observer.next('Anna');
setTimeout(() => { // 异步部分
observer.next('RxJS 30 days!');
observer.complete(); //停止observable,此后部分不会被显示。
observer.next("not work");
}, 30)
})
console.log('start');
observable.subscribe(function(value) { // 2.订阅这个observable对象,并为其设置观察者方法。
console.log(value);
});
console.log('end');
输出:
start
Jerry
Anna
end
RxJS 30 days!
对于subscribe方法来说,可以为其设定针对不同情况的不同处理,例如针对complete与异常抛出
var observer = {
next: function(value) { //.next()走这里
console.log(value);
},
error: function(error) { // 出现异常走这里
console.log('Error: ', error)
},
complete: function() { //.complete()走这里
console.log('complete')
}
}
observable.subscribe(observer) // 而后进行订阅
以上可以简化为传三个function参数:
observable.subscribe(
v => { console.log(v); },
e => { console.log('Error: ', e); },
() => { console.log('complete') }
)
订阅函数subscribe()具有自己的返回值,是一个subscription对象
该对象可以用来停止某些不会complete()的订阅过程,即unsubscribe();
observable的常用creation operator
这些操作符都是用来创建实例的操作符:
of()传入多个参数,observer将会将其依次next()传出,完成时则传出complete()
var source = Rx.Observable.of('Jerry', 'Anna');
from()与of()很相似,只不过传入的是一个可以被枚举的参数,例如array,set,iterator甚至是promise(可以使用fromPromise)等等(object和string应该能被传入)
var source = Rx.Observable.from(['Jerry', 'Anna']);
fromEvent()用于监听事件,在next中传回的将是被触发的事件对象
var source = Rx.Observable.fromEvent(document.body, 'click');
fromEventPattern()传入一个事件的触发与取消,监听一次?
var source = Rx.Observable
.fromEventPattern(
(handler) => egghead.addListener(handler),
(handler) => egghead.removeListener(handler)
);
empty()传入一个空的观测序列,被订阅后立刻输出complete
var source = Rx.Observable.empty();
never()传入一个永远不会结束但什么也不干的观测序列,被订阅后什么都不会发生
var source = Rx.Observable.never();
throw()传入一个立刻回抛出异常的观测序列,被订阅后立刻抛出这个错误
var source = Rx.Observable.throw('Oop!');
interval()传入一个按interval传入参数(单位为ms)间隔发出next(从0开始)的观测序列,其中next()传出的值为次数,由0开始
var source = Rx.Observable.interval(1000);
timer()与之类似,当传入一个参数时类似于setTimeout,当设定两个参数时,第一个参数表示第一次next抛出的时间,第二个参数表示每次next的间隔
var source = Rx.Observable.timer(1000, 5000);
var source = Rx.Observable.timer(1000);
分割线-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operator:
map()将原有observable按一定规则映射成为一个新的observable
var source = Rx.Observable.interval(1000);
var newest = source.map(x => x + 2);
mapTo()将原有observable按映射成为一个传出定值的observable
var source = Rx.Observable.interval(1000);
var newest = source.mapTo(2);
filter()将原有的observable根据规则过滤成为一个新的observable
var source = Rx.Observable.interval(1000);
var newest = source.filter(x => x % 2 === 0);
take()取原有的observable的前n项,并传出complete()
var source = Rx.Observable.interval(1000);
var example = source.take(3);
first()等同于take(1)
takeLast()指去最后n个,顺序依然是正序
var source = Rx.Observable.interval(1000).take(6);
var example = source.takeLast(2); // 输出4,5
last()等同于takeLast(1)
skip()跳过n个next
var source = Rx.Observable.interval(1000);
var example = source.skip(3);
takeUntil()在某件事发生时,出发observable的complete()
var source = Rx.Observable.interval(1000);
var click = Rx.Observable.fromEvent(document.body, 'click');
var example = source.takeUntil(click);
concat()把多个Observable合并成一个
var source = Rx.Observable.interval(1000).take(3);
var source2 = Rx.Observable.of(3)
var source3 = Rx.Observable.of(4,5,6)
var example = source.concat(source2, source3);
startWith()是在原observable发送之前添加一些不是observable但是需要被发送的元素
var source = Rx.Observable.interval(1000);
var example = source.startWith(0);
concatAll()将一个内含Observable的Observable中的所有Observable合并成为一个Observable
var obs1 = Rx.Observable.interval(1000).take(5);
var obs2 = Rx.Observable.interval(500).take(2);
var obs3 = Rx.Observable.interval(2000).take(1);
var source = Rx.Observable.of(obs1, obs2, obs3);
var example = source.concatAll();
concat和concatAll会严格按顺序执行,如上文例子输出为0,1,2,3,4,0,1,0
merge()与concat类似,但是最大的区别在于多个observable会并发进行,任意一个observable发送next时都会对之进行处理
var source = Rx.Observable.interval(500).take(3);
var source2 = Rx.Observable.interval(300).take(6);
var example = source.merge(source2);
一个简单的RxJs拖拽代码
const dragDOM = document.getElementById('drag');
const body = document.body;
const mouseDown = Rx.Observable.fromEvent(dragDOM, 'mousedown');
const mouseUp = Rx.Observable.fromEvent(body, 'mouseup');
const mouseMove = Rx.Observable.fromEvent(body, 'mousemove');
mouseDown
.map(event => mouseMove.takeUntil(mouseUp)) //这两行比较精髓个人感觉
.concatAll()
.map(event => ({ x: event.clientX, y: event.clientY }))
.subscribe(pos => {
dragDOM.style.left = pos.x + 'px';
dragDOM.style.top = pos.y + 'px';
})
分割线-------------------------------------------------------------------------------------------------------------------------------------------------------------------
combineLatest()每当一个observable输出数据时则调用回调函数,若另一个observable并没有数据输出则不调用回调函数。
var source = Rx.Observable.interval(500).take(3);
var newest = Rx.Observable.interval(300).take(6);
var example = source.combineLatest(newest, (x, y) => x + y);
source : ----0----1----2|
newest : --0--1--2--3--4--5|
combineLatest(newest, (x, y) => x + y);
example: ----01--23-4--(56)--7|
输出拆分为 0+0, 1+0, 2+0,1+2,3+1,4+1,2+4,5+2;
withLatestFrom()与combineLastest类似,但是只有主函数输出时才会执行回调函数
var main = Rx.Observable.from('hello').zip(Rx.Observable.interval(500), (x, y) => x);
var some = Rx.Observable.from([0,1,0,0,0,1]).zip(Rx.Observable.interval(300), (x, y) => x);
var example = main.withLatestFrom(some, (x, y) => {
return y === 1 ? x.toUpperCase() : x;
});
订阅后输出helLO
zip()则是把每个observable相同发送次数的值放在一次进行操作
var source = Rx.Observable.interval(500).take(3);
var newest = Rx.Observable.interval(300).take(6).takeLast(4);
var example = source.zip(newest, (x, y) => x + y);
source : ----0----1----2|
newest : --2--3--4--5|
zip(newest, (x, y) => x + y)
example: ----2----4----6|
输出拆分为:0+2,1+3,2+4
利用zip我们能很方便的将同步的一些observable变成异步的,比如
var source = Rx.Observable.from('hello');
var source2 = Rx.Observable.interval(100);
var example = source.zip(source2, (x, y) => x);
这个例子就能将hello的字母每经过100ms输出一个。
分割线-------------------------------------------------------------------------------------------------------------------------------------------------------------------
scan()类似于js的reduce方法,即会保留上一次next的结果值并传入下一次计算的回调函数,作为第一个参数
var source = Rx.Observable.from('hello')
.zip(Rx.Observable.interval(600), (x, y) => x);
var example = source.scan((origin, next) => origin + next, '');
source : ----h----e----l----l----o|
scan((origin, next) => origin + next, '')
example: ----h----(he)----(hel)----(hell)----(hello)|
buffer()会将一个observable的next输出暂存起来,直到另一个observable传出next时将缓存区内的所有数据通过数组形式传出。
var source = Rx.Observable.interval(300);
var source2 = Rx.Observable.interval(1000);
var example = source.buffer(source2);
source : --0--1--2--3--4--5--6--7..
source2: ---------0---------1--------...
buffer(source2)
example: ---------([0,1,2])---------([3,4,5])
bufferTime()则是设定一个缓存周期,每经过这一个周期则将缓存内的数据通过数组传出。
var source = Rx.Observable.interval(300);
var example = source.bufferTime(1000);
bufferCount()则设定一个缓存大小,每当缓存达到大小时将数据输出
var source = Rx.Observable.interval(300);
var example = source.bufferCount(3);
bufferToggle()传入一个Open Observable和一个Close Observable以及一个source Observable,每当Close传出一个
next时,查找Open的上一个next(),则将这两个next()区间内的所有source的next传出。
const source$ = Rx.Observable.interval(500);
const open$ = Rx.Observable.interval(1500);
const close$ = Rx.Observable.interval(1000);
const foo$ = source$.bufferToggle(open$, ( ) => {
return close$;
});
/**
---0---1---2---3---4---5---6---7---8---9----.... (source)
-----------1-----------2-----------3--------... (open)
--- ---x --- ---x --- ---x... (close)
bufferToggle(open$, () => close$)
------------------([2,3])-----([5.6])-----([8,9])--...
*/
bufferWhen()类似与buffer(),不过bufferWhen的参数是一个function,他的返回值为关闭buffer的observable
const open$ = Rx.Observable.interval(1000);
const click$ = Rx.Observable.fromEvent(document, 'click');
var w = open$.bufferWhen(( ) => click$);
w.subscribe(x => console.log(x))
// 每次点击都能进行一次分组
// 第二秒点击第一次:[0, 1, 2]
// 第六秒点击第二次:[3, 4, 5, 6]
分割线-------------------------------------------------------------------------------------------------------------------------------------------------------------------
delay()可以延迟observable一开始发送next的时间,也可以传递毫秒数,也可以传递一个时间。
var source = Rx.Observable.interval(300).take(5);
var example = source.delay(500);
var example2 = source.delay(new Date(Date.now() + 500)); //此二式结果相同
source : --0--1--2--3--4|
delay(500)
example: -------0--1--2--3--4|
delayWhen()和delay相似,但是最大的不同是他会延时每一个next(),而不像delay只会延时第一个next()
var source = Rx.Observable.interval(300).take(5);
var example = source
.delayWhen(
x => Rx.Observable.empty().delay(100 * x * x)
);
source : --0--1--2--3--4|
.delayWhen(x => Rx.Observable.empty().delay(100 * x * x));
example: --0---1----2-----3-----4|
debounce()传入一个debounce observable,每当source observable传出next时,不会立刻将之直接传出,而是将之缓存,
如果在收到debounce传出的next之前没有收到其他source传出的next,那么将此次缓存的next传出,否则则将新的source next存入缓存,并等待下一次debounce的来临。
debounceTime()则是一个debounce的简化版,他接收一个时间参数,等同于一个interval Operator创建的observable。
//疑问:complete是否与next效果相同,在下面例子中在观测前记录Date.now()并在送出next后几率Date.now()会发现时间相差会1.
var source = Rx.Observable.interval(300).take(5);
var oDebounce = Rx.Observable.interval(1000);
var example = source.debounceTime(1000);
var example2 = source.debounce(() => oDebounce); //此二式效果相同
source : --0--1--2--3--4|
debounceTime(1000)
example: --------------4|
网友评论