最近在学习 AnguarJS2 ,而 RXJS 在其中的异步操作里用得十分多,索性去网上找了找教程,却发现读起来晦涩难懂,后面绞尽脑汁才搞明白这个球。为了让大家充分了解到 RXJS 的作用,我们从最基础的异步回调讲起,然后再从 Promise过渡到 RXJS。
function print_msg(msg) {
//Do something with msg
console.log(msg);
}
function async_read(callback) {
// Some async_work start
// Async get data from a PORT into msg
// Some async_work end
callback(msg);
}
async_read(print_msg);
function my_console(value2) {
//Do something with value2
console.log(value2);
}
function async_work1(callback1, callback2) {
// some async_work start
//......get value1
// some async_work end
callback1(value1, callback2);
}
function async_work2(value1, callback2) {
// some async_work start and do something with value1
//......get value2
// some async_work end
callback2(value2);
}
async_work1(async_work2, my_console);
在例2中,我们将回调函数1(异步操作2)和回调函数2传给了异步操作1,以便在异步操作1完成时调用回调函数1(异步操作2),再将异步操作1得到的 value1 与回调函数2传给回调函数1(异步操作2),最终当回调函数1(异步操作2)完成后将调用回调函数2输出异步操作2得到的 value2 。当回调函数2也是异步操作的时候怎么办?难道真的这样一层套一层?这样的代码读起来晦涩易懂,我们要通过某种方式将其变得更简单,于是 Promise 出现了!
var promise = new Promise(function(resolve, reject) {
// Some async_work start
// Async get data from a PORT into msg
// Some async_work end
if (/* Async_work successed */) {
resolve(msg);
}
else {
reject(error);
}
});
promise.then(function(msg) {
//Do something with msg
console.log(msg)
}, function(error) {
// Failure, do something here
console.log(error);
});
在上例中,我们创建了一个 Promise 对象,并且传入了一个函数对象,注意这个函数并不是异步操作结束后将被调用的函数,而是用来初始化 Promise 的。这个函数接受2个参数 resolve 和 reject (后者可选),并且我们将异步操作全部移植入到这个函数中,当异步操作执行成功之后,调用了 resolve(msg),这是什么意思?很简单,如果我们用第一种方法,resolve 这一行肯定是 callback(msg),也就是调用回调函数并将异步得到的 msg 传给其。所以这里 resolve(msg) 的意思就是通知注册号的回调函数异步操作已经完成了,并且产出了可用的 msg 参数。那么回调函数是在哪里注册的呢?可用看到,之后我们又调用了 promise 的 then 方法,它接收一个函数对象,不错这个函数对象就是我们的回调函数。但是我们的 then 居然接收了2个回调函数, 很显然,第二个函数是用来处理 reject 通知过来的 error 的。
var promise = new Promise(function(resolve) {
// Some async_work1 start
// ......get value1
// Some async_work1 end
resolve(value1);
});
promise.then(function(value1) {
return new Promise(function(resolve) {
// Some async_work2 start
// ......get value2
// Some async_work2 end
resolve(value2);
})
.then(function(value2) {
//Do something with value2
console.log(value2);
})
Observable
: 可观察的数据序列.Observer
: 观察者实例,用来决定何时观察指定数据.Subscription
: 观察数据序列返回订阅实例.Operators
: Observable
的操作方法,包括转换数据序列,过滤等,所有的Operators
方法接受的参数是上一次发送的数据变更
的值,而方法返回值我们称之为发射新数据变更
.Subject
: 被观察对象.Schedulers
: 控制调度并发,即当Observable接受Subject的变更响应时,可以通过scheduler设置响应方式,目前内置的响应可以调用Object.keys(Rx.Subject)
查看。序列源实例
,该实例不具备发送数据的能力,相比之下通过new Rx.Subject
创建的观察对象实例
具备发送数据源的能力。序列源实例
可以订阅序列发射新数据变更时的响应方法(回调方法)序列源实例
可以销毁,而当订阅方法发生错误时也会自动销毁。序列源实例
的catch
方法可以捕获订阅方法发生的错误,同时序列源实例
可以接受从catch
方法返回值,作为新的序列源实例
const search$ = Rx.Observable.fromEvent(input, 'input'); //有个id为input的input DOM
search$.subscribe(function(event) {
//Do something with event
})
search$.subscribe(function(event) {
//Do other thing with event
})
上例中我们通过调用 const search$ = Observable.fromEvent(input, 'input') 方法创建了一个 Observable,这个对象有什么用呢?和 Promise 类似,我们可以调用其 subscribe 方法来传递回调函数,也就是上面所提到的观察者 Observer,并且可以有不限制个数的观察者(回调函数)。那么什么时候会触发这些回调函数呢?对于
fromEvent 方法创建的 Observable,在这个例子中,每当 fromEvent 参数中的 input DOM 的 'input' 被触发时,Observable 就会开始执行,执行什么?这里先这么理解,类似 Promise 的 resolve(args) 方法,它会调用 next(args) 方法,通知所有订阅过它的观察者(也就是通过 subscribe 传入的回调函数)有新的产品(args,也就是之前概念里的数据)可以用了,这个时候回调函数都会被调用。
//TypeScript
let func = value => {
return "message is" + value;
}
const search$ = Observable.fromEvent(input, 'input')
.map(e => e.target.value)
.filter(value => value.length >= 1)
.throttleTime(100)
.distinctUntilChanged()
.switchMap(value => func(value))
.subscribe(
x => renderSearchResult(x),
err => console.error(err)
)