The Reactive Extensions for JavaScript (RxJS)

来源:互联网 发布:lnmp 查看php日志 编辑:程序博客网 时间:2024/05/20 09:44

Rxjs是通过可观察者序列来构建异步的且事件驱动的项目的一组库,其中核心的类型Observable,其余的, (Observer, Schedulers, Subjects) 及ES5的数组扩展方法(map, filter, reduce, every, etc) 。

为什么需要响应式?

应用程序,特别是web上的已经因为Ajax革命,从简单的静态页面,改为 动态的DHTML(动态超文本标记语言)好多年。每次,当我们在应用上添加更多复杂的东西,更多数据,更多异步的行为。我们该如何管理全部?我们怎么规划它?“响应式的架构”是事件驱动的,有弹性的,可响应的。随着响应式变成的扩张,你需要所有的工具来帮助构建这些系统。


Observable:有着未来值或事件的invokable(叫唤的)集合的思想
Observer:知道如何监听通过Observable进行的值传递 的回调函数的集合
Subscription:Observable的执行,主要用于取消执行
Operators:纯粹的函数,能够让处理集合的函数式编程,使用ES5的数组扩展操作
Subject:等价于EventEmitter(事件触发器),并且是广播一个值或者事件给多个Observers的唯一方式
Schedulers:是集中的分发器,用于控制并发性,当计算发生在setTimeout或者requestAnimationFrame等等时允许我们调整

Pull & Push

Pull:Consumer决定什么时候从数据生产者那接受数据,Producer不知道什么时候数据会传递到Consumer
JS Function 是Pull system.function is a Producer of data,调用function的地方是consumer.
iterator.next() 是consumer

Push:Producer决定何时传递数据给Consumer,consumer不知道何时可以接收到数据。
Promise是最常见的push system。a promise 传递一个解决数据给注册的毁掉,但是和function不同,promise决定什么时候将数据push给回调。

RxJS引进Observables,一个新的push system for js.Observable 是多个数据的producer,推送他们给Observers(consumers).

functions和Observables都为延迟计算。如果你们没有调用function,函数内的代码将不会执行。Observables也一样,如果你没有用subscribe方法订阅它,observable里的代码将不会执行。
并且call和subscribe都是独立的操作:两个function调用触发两种独立的效果,两个Observable订阅触发两种独立的影响。

As opposed to EventEmitters which share the side effects and have eager execution regardless of the existence of subscribers, Observables have no shared execution and are lazy.

Observables 可以同步或异步地传递数据。

Observables和Function不同在于,Observables 可以返回多个值,function不行。

var foo = Rx.Observable.create(function (observer) {  console.log('Hello');  observer.next(42);  observer.next(100); // "return" another value  observer.next(200); // "return" yet another});console.log('before');foo.subscribe(function (x) {  console.log(x);});console.log('after');"before""Hello"42100200"after"

你也可以异步地返回值。(利用一个setTimeout)

var foo = Rx.Observable.create(function (observer) {  console.log('Hello');  observer.next(42);  observer.next(100);  observer.next(200);  setTimeout(() => {    observer.next(300); // happens asynchronously  }, 1000);});console.log('before');foo.subscribe(function (x) {  console.log(x);});console.log('after');"before""Hello"42100200"after"300

Core Observable concerns:

Creating Observables
Subscribing to Observables
Executing the Observable
Disposing Observables

Rx.Observable.create是Observable构造函数的别名,并且有一个参数:subscribe函数。

以下例子创建一个Observable在每一秒emit字符串‘hi’给Observer:

var observable = Rx.Observable.create(function subscribe(observer) {  var id = setInterval(() => {    observer.next('hi')  }, 1000);});

Subscribing to Observables(订阅Observables):

observable.subscribe(x => console.log(x));

observable.subscribe和Observable.create(function subscribe(ovserver){})中的subscribe名字一样不是巧合。
在库里,两者是不同的,但是为了实际目的,你可以把它们想成一样。

同时,这表明了subscribe没有在多个Observers中共享一个同样的Observable。当一个Observer调用observable.subscribe,在Observable.create(function subscribe(observer){})中的subscribe只运行给定的observer。
每个observable.subscribe为每个给定的observer触发独立的setup.

Subscribing to an Observable is like calling a function, providing callbacks where the data will be delivered to.

这和事件处理APIS 如 addEventListener/removeEventListener彻底不同.

随着observable.subscribe,给定的Observer并没有在Observable中注册listener,Observable甚至没有维持和Observers的联系。

一个subscribe call是简单开始observable执行和传递值或者事件给Observer的方式。

Executing Observables

Observable.create(function subscribe(observer) {…})表示一个Observable execution.
一个延迟计算值发生在每个订阅过的Observer,该执行一段时间后同步或异步地产生多个值。

There are three types of values an Observable Execution can deliver:

“Next” notification: 传递一个值如Number,String,Object,etc..
“Error” notification: 传递JS错误或异常
“Complete” notification: 不传值

其中,next是最重要的且最常见的,他们代表被传递给Observer的真实数据。
Error和Complete可能在Observable执行中只发生一次

var observable = Rx.Observable.create(function subscribe(observer) {  try {    observer.next(1);    observer.next(2);    observer.next(3);    observer.complete();  } catch (err) {    observer.error(err); // delivers an error if it caught one  }});

Disposing Observable Executions

因为Observable Executions 可能无限,并且很经常Observer希望在有限的时间内中止执行。
每个执行都是一个Observer所独有的,一但Observer已经接收完值,需要有中止执行的方式,来防止浪费性能和内存资源。

var observable = Rx.Observable.from([10, 20, 30]);var subscription = observable.subscribe(x => console.log(x));// Later:subscription.unsubscribe();

每个Observable必须在我们使用create()创建Observable时,定义如何销毁执行的资源。你可以return定制的unsubscribe function from function subscribe()。

var observable = Rx.Observable.create(function subscribe(observer) {  // Keep track of the interval resource  var intervalID = setInterval(() => {    observer.next('hi');  }, 1000);  // Provide a way of canceling and disposing the interval resource  return function unsubscribe() {    clearInterval(intervalID);  };});function subscribe(observer) {  var intervalID = setInterval(() => {    observer.next('hi');  }, 1000);  return function unsubscribe() {    clearInterval(intervalID);  };}var unsubscribe = subscribe({next: (x) => console.log(x)});// Later:unsubscribe(); // dispose the resources

Observer

Observer是通过Observable传递值的consumer。Observers 简单来说就是一组回调函数

var observer = {  next: x => console.log('Observer got a next value: ' + x),  error: err => console.error('Observer got an error: ' + err),  complete: () => console.log('Observer got a complete notification'),};observable.subscribe(observer);

如果你没有提供任一回调,Observable的执行还是会正常的发生,除了某些类型的通知会被忽略,因为他们在Observer里没有相应的回调。

observable.subscribe(  x => console.log('Observer got a next value: ' + x),  err => console.error('Observer got an error: ' + err),  () => console.log('Observer got a complete notification'));

Subscription

A Subscription is an object that represents a disposable resource,usually the execution of an Observable. A Subscription has one important method, unsubscribe, that takes no argument and just disposes the resource held by the subscription. In previous versions of RxJS, Subscription was called “Disposable”.
Subscriptions can also be put together, so that a call to an unsubscribe() of one Subscription may unsubscribe multiple Subscriptions. You can do this by “adding” one subscription into another:

var observable1 = Rx.Observable.interval(400);var observable2 = Rx.Observable.interval(300);var subscription = observable1.subscribe(x => console.log('first: ' + x));var childSubscription = observable2.subscribe(x => console.log('second: ' + x));subscription.add(childSubscription);setTimeout(() => {  // Unsubscribes BOTH subscription and childSubscription  subscription.unsubscribe();}, 1000);

When executed, we see in the console:

second: 0first: 0second: 1first: 1second: 2

Subscriptions also have a remove(otherSubscription) method, in order to undo the addition of a child Subscription.

Subject

Subject 是Observable的特殊类型,允许多路广播值给多个Observers。当普通的Observables为单一广播时(每个订阅过的Observer拥有一个独立的Observable执行),Subjects为多路广播。

A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners.

每个Subject是一个Observable。给予一个Subject,你可以subscribe它,提供一个将会正常接收值的Observer。从Observer的角度来说,
他不知道Observable 执行 会来自一个普通的单一Observable或者多路广播的Subject。

每个Subject本身也是一个Observer。它也有着方法next(v), error(e), and complete().Subject需要有新值传递进来,只要call next(),然后就会多路广播给Observers来注册监听这个Subject。

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);With the following output on the console:observerA: 1observerB: 1observerA: 2observerB: 2

Subject同时也是Observer,意味着,你可能需要提供一个Subject作为Observer订阅的参数,如下:

var subject = new Rx.Subject();subject.subscribe({  next: (v) => console.log('observerA: ' + v)});subject.subscribe({  next: (v) => console.log('observerB: ' + v)});var observable = Rx.Observable.from([1, 2, 3]);observable.subscribe(subject); // You can subscribe providing a Subject

Which executes as:

observerA: 1observerB: 1observerA: 2observerB: 2observerA: 3observerB: 3

Multicasted Observables

0 0