Rxjs英文官网域名已经变为 https://rxjs-dev.firebaseapp.com/
本文中的例子均采用5.3版本
感受Rxjs
第一个小练习
学习用observable的方式来注册事件监听,注释的代码为注册事件监听器的常规写法。
<!DOCTYPE html> <html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>第一个Rxjs练习</title>
</head><body>
<button>click me</button>
<script src="https://unpkg.com/@reactivex/rxjs@5.3.0/dist/global/Rx.js"></script><script>
var button = document.querySelector('button');
// button.addEventListener('click',(event)=>{ console.log(event)});
Rx.Observable.fromEvent(button, 'click').subscribe(
(event) => console.log(event)
);
</script>
</body>
</html>
第二个练习 学习用observable的方式控制事件的流动性 ,注释代码为传统方式何控制一秒钟内最多点击一次
<!DOCTYPE html>
<html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Flow</title>
</head><body>
<button>click me</button>
<script src="https://unpkg.com/@reactivex/rxjs@5.3.0/dist/global/Rx.js"></script><script>
var button = document.querySelector('button');
/* var count = 0;
var rate = 1000;
var lastClick = Date.now() - rate;
button.addEventListener('click', () => {
if (Date.now() - lastClick >= rate) {
console.log(Clicked ${++count} times
);
lastClick = Date.now();
}
}) */Rx.Observable.fromEvent(button, 'click') .throttleTime(1000) .subscribe(event => console.log(event));
</script>
</body>
</html>
我们继续对第二个例子做一些小变化 ,引入map 可以过滤事件返回的数据,在这个例子中我们过滤了event数据,只保留了它的clientY属性,这样在订阅(subscribe)方法中就只监听到clientY的数据
Rx.Observable.fromEvent(button, 'click')
.throttleTime(1000)
.map((data) => {
return data.clientY
})
.subscribe(coordinate => console.log(coordinate));
可观察对象 观察者 订阅的关系
数据流
订阅方法的两种写法
下面用代码来说明subscribe方法的写法 ,需要注意的是点击事件不存在complete方法 所有你不会看到complete方法被调用。 用户每点一次就执行一次next方法
<!DOCTYPE html>
<html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
</head><body>
<button>click me</button>
<script src="https://unpkg.com/@reactivex/rxjs@5.3.0/dist/global/Rx.js"></script><script>
var button = document.querySelector('button');var observer = { next: function (value) { console.log(value); }, error: function (error) { console.log(error); }, complete: function () { console.log('Completed'); } } Rx.Observable.fromEvent(button, 'click') .subscribe(observer);
</script>
</body>
</html>
形象了解创建 订阅 执行 Observable(可观察对象)的过程
接着我们学习如何用create方法来创建数据流, 来更清晰的理解可观察对象,观察者和订阅之间的关系。注意本例子中的数据是同步数据,虽然rxjs是专门处理异步数据的,但是不仅限于处理异步数据,同步数据也可以。 我们需要知道的是 当create方法里 调用error方法 ,则后面的任何方法都不再执行。 当调用complete方法后 后面的方法也都不再执行。
<!DOCTYPE html>
<html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
</head><body>
<script src="https://unpkg.com/@reactivex/rxjs@5.3.0/dist/global/Rx.js"></script><script>
var observer = {
next: function (value) {
console.log(value);
},
error: function (error) {
console.log(error);
},
complete: function () {
console.log('Completed');
}
}Rx.Observable.create(function (obs) { obs.next('A value'); obs.next('A second value'); obs.error('Error'); obs.complete(); obs.next('A thrid value'); }) .subscribe(observer);
</script>
</body>
</html>
其实我们也可以用setTimeout函数来模拟异步数据流,来观察返回的数据流。 写法如下
var observer = {
next: function (value) {
console.log(value);
},
error: function (error) {
console.log(error);
},
complete: function () {
console.log('Completed');
}
}Rx.Observable.create(function (obs) { obs.next('A value'); obs.next('A second value'); setTimeout(function () { obs.complete(); }, 2000) //obs.error('Error'); obs.next('A thrid value'); }) .subscribe(observer);</code></pre></div></div><p>接着我们用create方法再把我们第一个按钮点击的例子重写一遍,以便更深刻理解rxjs观察订阅的机制。 代码如下</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0"><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
</head><body>
<script src="https://unpkg.com/@reactivex/rxjs@5.3.0/dist/global/Rx.js"></script>
<button>Click me</button>
<script>
var button = document.querySelector('button');
var observer = {
next: function (value) {
console.log(value);
},
error: function (error) {
console.log(error);
},
complete: function () {
console.log('Completed');
}
}Rx.Observable.create(function (obs) { button.onclick = function (event) { obs.next(event); } }) .subscribe(observer);
</script>
</body>
</html>
使用unsubscribe方法清理 Observable (可观察对象)
对于那些已经不再使用的可观察对象会停留在内存中,有可能造成内存泄露,因此我们可以手工清理这些可观察对象。
下面的代码模拟在5秒之后清除了订阅机制,5秒之后你继续点击按钮将接收不到期待订阅的数据。
<!DOCTYPE html>
<html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
</head><body>
<script src="https://unpkg.com/@reactivex/rxjs@5.3.0/dist/global/Rx.js"></script>
<button>Click me</button>
<script>
var button = document.querySelector('button');
var observer = {
next: function (value) {
console.log(value);
},
error: function (error) {
console.log(error);
},
complete: function () {
console.log('Completed');
}
}var subscription = Rx.Observable.create(function (obs) { button.onclick = function (event) { obs.next(event); } }) .subscribe(observer); setTimeout(function () { subscription.unsubscribe(); }, 5000);
</script>
</body>
</html>
Operators 操作符
常见的操作符如map(对订阅的数据过滤),throttleTime(延迟订阅的频率)