RxJS 入门要知道的基础知识

RxJS 是一个由 Observable sequences 來组合非同步行为事件基础程序的库

RxJS 提供了一套完整的非同步解决方案,让我们在面对各种非同步操作时,不管是 Event, AJAX, 还是Animation 等,都可以使用相同的 API 进行操作

這也被称为 Functional Reactive Programming,更确切的说是指 Functional Programming 及 Reactive Programming 两个编程思想的结合。

Functional Programming 重要特性

函数式编程都是表达式(expression) 不会是陈述式(statement)

  • 表达式是一个运算过程,一定会有返回值,例如执行一个function add(1,2)
  • 陈述式则是表现某个行为,譬如赋值给变量a = 1;

Pure function 是指 给一个 function 相同的参数,永远会返回相同的返回值,并且沒有任何副作用(Side Effect)

前端常见的side effect:

  • 发送http request
  • 在画面印出值或者log
  • 获得用户的input
  • 查询 DOM 对象

Observable

Observalue 可以被订阅(subscribe),订阅 Observalue 的对象又称为观察者(observer)。观察者是一个具有三个方法的对象,每当 Observable 发生事件时,观察者便会调用相对应的方法

觀察者的三個方法(method):

  • next:每当 Observable 发出新的值时,next 方法就会被调用
  • complete:当 Observable 没有其他的值可以取时,complete 方法就会被调用,complete 调用之后,next 方法不会再起作用
  • error:每当 Observable 发生错误时
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var observable = Rx.Observable
.create((observer)=>{
observer.next('Jerry')
observer.next('Anna')
observer.complete()
observer.next('not work')
})
//定义一个观察者,具备三个方法
var observer = {
next: function(value) {
console.log(value)
}
error: function(error) {
console.log(error)
}
complete: function() {
console.log('complete')
}
}
//用定义好的观察者来订阅这个observable
observable.subscribute(observer)
//结果会输出
/*Jerry
Anna
complete*/

观察者可以是不完整的,可以只具有一个next方法

也可以直接把三个方法按顺序传入

1
2
3
4
5
observable.subscribe(
value => { console.log(value); },
error => { console.log('Error: ', error); },
() => { console.log('complete') }
)

Observable 创建实例的几个常用方法

  • create

    同上

  • of

    1
    2
    //这个参数是一个list
    var sourse = Rx.Observable.of('Jerry', 'Anna')
  • from

    1
    2
    3
    4
    var arr = ['Jerry', 'Anna', 2016, 2017, '30 days']
    var sourse = Rx.Observable.from(arr)
    //这个参数可以是Array, Set, WeakSet, Iterator ,String, Promise 等..
    //如果是字符串的话,会把字符串里的字符一个个读取
    1
    2
    3
    4
    5
    6
    7
    //传入 Promise 实例,当正常回传 (resolve) 会传入 next,有错误 (reject) 就传到 error
    var source = Rx.Observable
    .from(new Promise((resolve, reject) => { //這裡的 form 也可以改成 fromPromise ,結果相同
    setTimeout(() => {
    resolve('Hello RxJS!');
    },3000)
    }))
  • fromEvent

    1
    2
    var source = Rx.Observable.fromEvent(document.body, 'click')
    //第一个参数是 DOM 元素,第二个参数是要监听的事件名称
  • fromEventPattern

  • empty

    1
    2
    var source = Rx.Observable.empty();
    //empty 會給我們一個空的 observable,如果我們訂閱這個 observable ,會立即送出 complete 的訊息!
  • never

    1
    2
    var source = Rx.Observable.never();
    //never 會給我們一個無窮的 observable,如果我們訂閱它则...什麼事都不會發生,它就是一個一直存在但卻什麼都不做的 observable
  • throw

    1
    2
    var source = Rx.Observable.throw('Oop!');
    //抛错误
  • interval

    1
    2
    3
    var source = Rx.Observable.interval(1000);
    //interval 有一個参数必须是数值(Number),這个数值代表发出讯号的间隔时间(ms)。
    //这段程序会持续每隔一秒发出一個从0开始递增的数值
  • timer

    1
    2
    3
    4
    var source = Rx.Observable.timer(1000, 5000);
    //第一个参数代表发出第一个值等待的时间(ms),第二个参数表示第一次之后发送值的时间间隔,所以上面这段程序会先等1s送出0之后,每隔5s送出1,2,3,4,5....
    //timer的第一个参数还可以是日期(Date),就会等到指定的时间再发送第一个值
    //也可以只接受一个参数,等一秒送出0同时结束通知

Sbuscription

在订阅 observable 之后,会返回一个 subscription 对象,这个对象具有释放资源的 unsubscribe 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var source = Rx.Observable.timer(1000, 1000)
var subscription = source.subscribe({
next: function(value) {
console.log(value)
},
complete: function() {
console.log('complete')
}
})
setTimeout(() => {
subscription.unsubscribe()
}, 5000)
//0
//1
//2
//3
//4

Events observable 盡量不要用 unsubscribe ,通常我們會使用 takeUntil,在某個事件發生後來完成 Event observable

operator

operators 就是一个个被附加到 Observable 对象的函数,像map, filter… 等等。这些函数会收到原本的observable 并回传一个新的 observable

  • map
  • filter
  • mapTo 可以把傳進來的值改成一個固定的值
  • ………..
  • 更多
1
2
3
4
5
6
7
var source = Rx.Observable.interval(1000);
var newest = source.mapTo(2);
newest.subscribe(console.log);
// 2
// 2
// 2
// 2..

Marble diagrams

1
2
var source = Rx.Observable.interval(1000);
var newest = source.map(x => x + 1);

這時 Marble diagrams 就會長像這樣

1
2
3
source: -----0-----1-----2-----3--...
map(x => x + 1)
newest: -----1-----2-----3-----4--...