最近因为Angular2了解到了RxJS这个东西,总的来说,RxJS的出现也是为了解决异步回调的,它针对于事件序列。
RxJS是一个通过使用可观察序列来构建异步和基于事件的程序的库。它提供了一个核心类型:Observable、卫星类型(大概是这些类型均围绕于Observable,也就是Observable是根基,而这些是辅助类型):Observer、Schedulers、Subjects)和操作符-衍生自一些数组方法,使得我们可以把异步事件以集合的方式进行处理。
把RxJS当做一个针对事件的Lodash(一个JS库)。
ReactiveX将观察者模式与迭代器模式和使用集合的函数式编程组合在一起,来满足这种管理事件序列的理想方式。
typescript + webpack 完成前端环境搭建
上述是我的项目目录树
src用来保存源文件,dist用来保存编译好的输出的文件
下面是我的webpack配置文件 webpack.config.js
const webpack = require('webpack');
module.exports = {
entry:__dirname + '\\src\\main.ts',
output:{
filename:"main.js",
path:__dirname + "\\dist"
},
plugins:[
new webpack.HotModuleReplacementPlugin()
],
//loaders
module:{
rules:[
{
loader:'json',
test:'/\.json$/'
}
]
},
devServer:{
contentBase:"./dist/",
historyApiFallback:true,
inline:true,
hot:true,
por们接下来要用到的webpack-dev-server
Observable 被翻译过来是可观察对象,它实现了观察者模式,我们可以用最常用的方法(用observable
create方法)来
创建一个Observable对象。
在此之前,你必须保证你正确安装了Rxjs,使用npm安装rxjs,对于npm项目的搭建这里就不必大费口舌了。
npm install --save--dev rxjs
首先,需要引入Rx模块
import * as Rx from 'rxjs/Rx'
之后我们可以创建一个observable
let observable = Rx.Observable.create(observer => {
observer.next(1);
observer.next(2);
observer.next(3);
observer.complete();
});
之后我们可以订阅它,observable就跟它的名字一样,是一个可观察对象,在观察者模式中,我们通常把它叫做被订阅者,两者意思都是一样的。现在我们来创建一个观察者
let observer = {
next:data => console.log(`get a data , the data is ${data}`),
error:err => console.log(JSON.stringify(err)),
complete:() => console.log(`complete`)
}
然后我们再来订阅这个observable对象,使用subscribe方法进行订阅,将观察者对象传递进去
observable.subscribe(observer);
之后我们运行webpack-dev-server。
webpack-dev-server --inline
在浏览器的console看到以下的输出信息
1
2
3
complete
next , error ,complete方法是属于观察者的,next决定传递一个什么样的数据给观察者,如果过程中有发生错误,就会产生一个error对象,发射过去,complete代表整个处理(dispose)过程已经完毕。
例如我们在complete下面再次发射一个数值4,观察者却收不到整个消息。
let observable = Rx.Observable.create(observer => {
observer.next(1);
observer.next(2);
observer.next(3);
observer.complete();
observer.next(4);
});
看到控制台打印的结果:
1
2
3
complete
上面我们调用了Observable的静态方法create进行创建,返回一个Observable对象,除此之外,RxJS还提供了了很多的更快捷的创建方法,比如:
let observable = Rx.Observable.from([1,2,3,4,5]);
from方法接受一个数组为参数,在该observable被订阅时,该数组里的内容都会被发射出去。
observable.subscribe(x => console.log(`this data is ${x}`));
output:
1
2
3
4
5
下面来做一个更加常见的例子。
经常与DOM交互中,避免不了订阅DOM事件。
订阅button的click事件
let btn = document.querySelector('button');
btn.addEventListener('click',e => {
console.log('cliked');
});
而在Observable中,你可以这样做。
import * as Rx from 'rxjs/Rx'
let btn = document.querySelector('button');
Rx.Observable.fromEvent(btn,'click')
.subscribe(e => {
console.log('clicked');
});
订阅Observable是RxJS编程中比较常见的操作。
我们先来看一下前面是如何创建一个Observable的。
let observable = Rx.Observable.create(observer => {
obserber.next(1);
});
很显然,这里create方法里的参数传递了一个observer,这个observer实际上就是观察者对象。这里传入create方法里的是一个匿名的函数。如果不匿名,它可能是这样的。
let observable = Rx.Observable.create(function subscribe(observer){
obserber.next(1);
});
它实际上是subscribe方法,当我们调用observable的subscribe方法时,它会把对应的数值发射到对应的观察者对象上,也就是说,各个观察者对象是相互独立的。
let subscription1 = observable.subscribe(x => console.log(`listener1 : get a data is ${x}`));
let subscription2 = observable.subscribe(x => console.log(`listener2 : get a data is ${x}`));
output :
1
1
前面说了Observer(订阅者)最主要的方法就是next , error 和complete。
next负责发送一个数据给观察者
error是封装异常对象然后发送给观察者
complete表示已经执行完毕
但是在实际的开发中,我们捕获异常最好是用传统的try catch语句,然后发送异常对象
let observable = Rx.Observable.create(function subscribe(observer){
try{
observer.next(1);
throw new Error('this is a test');
}
catch(e){
observer.error(e);
}
});
subscribe
observable.subscribe(x => console.log(`the data is ${x}`),err => console.log(`have a err , the err object is ${JSON.stringify(err)}`));
最后我们需要了解如何取消订阅。比如我们有一个每一秒向观察者发送一个值的Observable
let observable = Rx.Observable.create(observer => {
let i = 0;
setInterval(() => {
observer.next(i++);
},1000);
})
下面订阅它 , 我们会看到每秒打印的数值
observable.subscribe(x => console.log(x));
output :
0
1
2
3
4
...
现在我们想要在第一个值打印完毕之后不再接着打印后面的值,这个的解决办法有两种
1.添加complete方法
我们只需修改一下create方法,就能实现这个效果了,因为complete方法执行完毕后,后面的值都不会发射
let observable = Rx.Observable.create(observer => {
let i = 0;
setInterval(() => {
observer.next(i++);
observer.complete();
},1000);
})
output :
0
2.执行unsubscribe方法
调用observable的subscribe方法返回的是一个subscription对象,它有一个unsubscribe方法可以取消订阅
因此,我们可以这样做
let observable = Rx.Observable.create(observer => {
let i = 0;
setInterval(() => {
observer.next(i++);
},1000);
})
let subscription = observable.subscribe({
next:x => console.log(`the data is ${x}`),
error:err => console.log(`have a err , the err object is ${JSON.stringify(err)}`)
});
setTimeout(() => {
subscription.unsubscribe();
},1100);
可以看到console的打印
the data is 0