使用场景
- 在复杂的,频繁的异步请求场景,使用rxjs。
- 在依赖的多个异步数据,决定渲染的情景,使用rxjs。
总之:在前台频繁的、大量的、和后台数据交互的复杂项目里面,使用rxjs(web端,iOS,android端等,客户端都可考虑使用)
rxjs初步认识
- 数据和数据观察者的绑定。数据变化,观察者动作——监听或者观察者模式。
- 观察者的迭代执行动作——观察者注册任意个异步或同步动作,迭代执行。
hello world
let start = Rx.Observable.create((observer) => {
observer.next('hello world')
});
start.subscribe((a) => {
console.log(a)
})
# >>>
hello world
核心对象(概念)
-
Observable 可观察对象
数据,动作等进行包装后,变成observable可观察对象,供observer观察者监听 -
Observer 观察者
一些列的回调函数,用来应对Observable的变化。 -
Subscription (订阅)
将可观察对象和观察者建立起关系。 -
Operator(操作符)
库提供的方法,强大。就像js数组提供了map、filter、reduce等方法一样。 -
subject(主体)
subject像是维护着一个监听者的注册表。
当有新的事件发生时,广播给各个监听者。 -
Schedulers (调度器)
先不管,目前没用到,也不影响使用
基本示例
1
let firstObservable = Rx.of('one', 'two');
firstObservable.subscribe((a) => {
console.log(a)
})
firstObservable.subscribe((a) => {
console.log(a+'-222')
})
# >>>
one
two
one-222
two-222
2
let secondObservable = Rx.Observable.create((data) => {
let a = 0;
//模拟异步请求
setInterval(() => {
data.next(a)
a += 1
}, 1000)
});
console.log('just before subscribe');
secondObservable.subscribe((a) => {
console.log(a + '11')
});
secondObservable.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');
# >>>
just before subscribe
just after subscribe
011
got value 0
111
got value 1
211
got value 2
311
got value 3
...
3, subject
let firstObservable = Rx.of('one', 'two');
firstObservable.subscribe((a) => {
console.log(a)
});
firstObservable.subscribe((a) => {
console.log(a+'-222')
})
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);
#>>>
one
two
one-222
two-222
observerA: 1
observerB: 1
observerA: 2
observerB: 2
状态控制
监听input输入框得变化,控制处理动作的流动或者规则
var input = Rx.Observable.fromEvent(document.querySelector('input'), 'input');
// 过滤掉小于3个字符长度的目标值
input.filter(event => event.target.value.length > 2)
.map(event => event.target.value)
.subscribe(value => console.log(value));
//延迟200毫秒
input.delay(200)
.map(event => event.target.value)
.subscribe(value => console.log(value));
//一秒内触发一次
input.throttleTime(1000)
.map(event => event.target.value)
.subscribe(value => console.log('一秒内触发一次-throttleTime' + value));
// 停止输入后200ms方能通过最新的那个事件
input.debounceTime(1000)
.map(event => event.target.value)
.subscribe(value => console.log('停止输入1000毫秒后-debounceTime' + value));
//处理三次后停止
input.take(3)
.map(event => event.target.value)
.subscribe(value => console.log('3次事件后停止流' + value));
// 直到其他 observable 触发事件才停止事件流
var stopStream = Rx.Observable.fromEvent(document.querySelector('button'), 'click');
input.takeUntil(stopStream)
.map(event => event.target.value)
.subscribe(value => console.log('button' + value)); // "hello" (点击才能看到)
产生值
//输入 hello world
var input = Rx.Observable.fromEvent(document.querySelector('input'), 'input');
// 传递一个新的值
input.map(event => event.target.value)
.subscribe(value => console.log('map'+value));
// 通过提取属性传递一个新的值---将对象的一个值提取出来
input.pluck('target', 'value')
.subscribe(value => console.log('pluck'+value));
// 传递之前的两个值
input.pluck('target', 'value').pairwise()
.subscribe(value => console.log('pluck/pairwise'+value)); // ["h", "he"]
// 只会通过唯一的值--一次输出一个且历史上重复输入,不会输出。
input.pluck('data').distinct()
.subscribe(value => console.log('distinct'+value)); // "helo wrd"
// 不会传递重复的值,上一个和当前值
input.pluck('data').distinctUntilChanged()
.subscribe(value => console.log('distinctUntilChanged'+value)); // "helo world"
应用状态的保持
rxjs使用的是纯函数。但是应用是有状态的,可以使用scan来累计状态
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
// 对流进行 scan (reduce) 操作,以获取 count 的值
.scan(count => count + 1, 0)
// 每次改变时都在元素上设置 count
.subscribe(count => document.querySelector('#count').innerHTML = count);
//使用merge将多个observables 合并在一起,监听处理
var increaseButton = document.querySelector('#increase');
var increase = Rx.Observable.fromEvent(increaseButton, 'click')
// 我们再一次映射到一个函数,它会增加 count
.map(() => state => Object.assign({}, state, {count: state.count + 1}));
var decreaseButton = document.querySelector('#decrease');
var decrease = Rx.Observable.fromEvent(decreaseButton, 'click')
// 我们还是映射到一个函数,它会减少 count
.map(() => state => Object.assign({}, state, {count: state.count - 1}));
var inputElement = document.querySelector('#input');
var input = Rx.Observable.fromEvent(inputElement, 'keypress')
// 我们还将按键事件映射成一个函数,它会产生一个叫做 inputValue 状态
.map(event => state => Object.assign({}, state, {inputValue: event.target.value}));
// 我们将这三个改变状态的 observables 进行合并
var state = Rx.Observable.merge(
increase,
decrease,
input
).scan((state, changeFn) => changeFn(state), {
count: 0,
inputValue: ''
});
// 我们订阅状态的变化并更新 DOM
state.subscribe((state) => {
document.querySelector('#count').innerHTML = state.count;
document.querySelector('#hello').innerHTML = 'Hello ' + state.inputValue;
});