该系列教程建立在有一定promise知识的前端同学身上,因为比较抽象,我们在例子中论证说明。
eg1.
var button = document.querySelector('button');
button.addEventListener('click', () => console.log('Clicked!'));
Using RxJS you create an observable instead.
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.subscribe(() => console.log('Clicked!'));
关键字 Observable subscribe 有点像观察者模式
eg2
var count = 0;
var button = document.querySelector('button');
button.addEventListener('click', () => console.log(`Clicked ${++count} times`));
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.scan(count => count + 1, 0) //可以把0改成2 表示从2开始加
.subscribe(count => console.log(`Clicked ${count} times`));
//scan 观察一个变量从0开始 有点像reduce 上一次的返回是这一次的输入
这里我们加入了一个scan 响应点击事件 更新数据
eg3
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.throttleTime(1000)
.scan(count => count + 1, 0)
.subscribe(count => console.log(`Clicked ${count} times`));
throttleTime(1000) 函数截流,不懂自行google,表示1s内点击无效
是不是也比太难,但是也觉得还没过瘾,咱们接着看。。。
eg4
var count = 0;
var rate = 1000;
var lastClick = Date.now() - rate;
var button = document.querySelector('button');
button.addEventListener('click', (event) => {
if (Date.now() - lastClick >= rate) {
count += event.clientX;
console.log(count)
lastClick = Date.now();
}
});
//这段代码想干嘛 叠加每次鼠标点击的clientX值嘛 不懂clientX自行google
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.throttleTime(1000)
.map(event => event.clientX)
.scan((count, clientX) => count + clientX, 0)
.subscribe(count => console.log(count));
下面这段代码很精神 ,注意每回点击的event.ClientX 传给了scan函数里面的clientX
你可以写成.map(event => event.clientY)试试 不影响scan里面的clientX
经过上面的例子大概也看出一下端倪来了,下面就来介绍observable可观察对象
eg1
var observable = Rx.Observable.create(function (observer) {
observer.next(1);
observer.next(2);
observer.next(3);
setTimeout(() => {
observer.next(4);
observer.complete();
}, 1000);
});
console.log('just before subscribe');
observable.subscribe({
next: x => console.log('got value ' + x),
error: err => console.error('something wrong occurred: ' + err),
complete: () => console.log('done'),
});
console.log('just after subscribe');
//尝试下面这个写法你就知道了
var foo = Rx.Observable.create(function (observer) {
console.log('Hello');
observer.next(42); observer.next(41);console.log('Hellos');observer.next(49)
});
foo.subscribe(function (x) {
console.log(x);
});
这里输出什么我就不写了,大家自己动手试一下,注意异步的问题。
我们来练习一下
1.每秒向观察者发射一个字符串"hi"的可观察对象。
var observable = Rx.Observable.create(function subscribe(observer) {
var id = setInterval(() => {
observer.next('hi')
}, 1000);
});
2.订阅可观察对象
observable.subscribe(x => console.log(x));
哇 是不是很简单
注意下面这段代码
var observable = Rx.Observable.create(function subscribe(observer) {
observer.next(1);
observer.next(2);
observer.next(3);
observer.complete();
observer.next(4); // Is not delivered because it would violate the contract
});
// observer.complete(); 在前 4不会被输出
eg2
var observable = Rx.Observable.from([10, 20, 30]);
相当于
var observable = Rx.Observable.create(function subscribe(observer) {
observer.next(1);
observer.next(2);
observer.next(3);
}
// 大家可以动手尝试
observable可以调用unsubscribe 方法 结束观察
var observable = Rx.Observable.create(function subscribe(observer) {
// Keep track of the interval resource
var intervalID = setInterval(() => {
observer.next('hi');
}, 1000);
return function unsubscribe() {
//这个方法实际上是重写 就是说这个return写不写都一样,后面都可以调用unsubscribe
console.log('价格打印')
clearInterval(intervalID);
};
});
var subscription = observable.subscribe(x => console.log(x));
subscription.unsubscribe();
//
咱们用原声的写一个
function subscribe(observer) {
var intervalID = setInterval(() => {
observer.next('hi');
}, 1000);
return function unsubscribe() {
clearInterval(intervalID);
};
}
var unsubscribe = subscribe({next: (x) => console.log(x)});
unsubscribe(); // dispose the resources
是不是觉得也没什么难的,当然这只是开始,在angular4 http中会经常用到
接下来咱们看点有趣的
var observable1 = Rx.Observable.interval(400);
var observable2 = Rx.Observable.interval(300);
var subscription = observable1.subscribe(x => console.log('first: ' + x));
var childSubscription = observable2.subscribe(x => console.log('second: ' + x));
subscription.add(childSubscription);
setTimeout(() => {
// Unsubscribes BOTH subscription and childSubscription
subscription.unsubscribe();
}, 1000);
second: 0
first: 0
second: 1
first: 1
second: 2
大家到控制台去打印一下,这种操作是把2个observable叠加在一起,注意顺序问题,这里是subscription在前面,所以要用他去unsubscribe
其实现在已经算完全入门了Rxjs了,最后再看一个subject吧
eg1
var subject = new Rx.Subject();
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
subject.next(1);
subject.next(2);
output:
observerA: 1
observerB: 1
observerA: 2
observerB: 2
这是个什么意思,这回是先subscribe(订阅),但是没反应,直到后面用了.next()才有输出。
每一个Subject都是一个observable可观察对象,给定一个Subject后,你可以订阅它,提供的观察者将会正常的开始接收值。
eg2
var subject = new Rx.Subject();
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
var observable = Rx.Observable.from([1, 2, 3]);
observable.subscribe(subject);
observerA: 1
observerB: 1
observerA: 2
observerB: 2
observerA: 3
observerB: 3
这里和前面不一样的就是所有订阅的都一起打印
下面有一个综合性的例子,其实也不太难哟
eg3
var source = Rx.Observable.interval(500);
var subject = new Rx.Subject();
var refCounted = source.multicast(subject).refCount();
var subscription1,subscription2,subscriptionConnect;
console.log('observerA subscribed');
subscription1 = refCounted.subscribe({
next: (v) => console.log('observerA: ' + v)
});
setTimeout(() => {
console.log('observerB subscribed');
subscription2 = refCounted.subscribe({
next: (v) => console.log('observerB: ' + v)
});
}, 600);
//这里解除了subscription1 时间是1200 前面的interval是500 所以‘observerA’会被输出2次
setTimeout(() => {
console.log('observerA unsubscribed');
subscription1.unsubscribe();
}, 1200);
// 2s后 subscription2.unsubscribe() 所有的interval都停止了
setTimeout(() => {
console.log('observerB unsubscribed');
subscription2.unsubscribe();
}, 2000);
observerA subscribed
observerA: 0
observerB subscribed
observerA: 1
observerB: 1
observerA unsubscribed
observerB: 2
observerB unsubscribed
这个稍微有点复杂,有条件的同学可以再看一下
最后一个例子
var subject = new Rx.BehaviorSubject(0); // 0 is the initial value
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.next(1);
subject.next(2);subject.next(3);
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
subject.next(4);
VM430:4 observerA: 0
VM430:4 observerA: 1
VM430:4 observerA: 2
VM430:4 observerA: 3
VM430:11 observerB: 3
VM430:4 observerA: 4
VM430:11 observerB: 4
new Rx.BehaviorSubject(0); 很关键,所以一开始就是0
注意一点是 observerB 会输出距他上面最近的一个next值