Original Address: https://segmentfault.com/a/1190000012669794
introduction
When developing ngx (angular 2+) application, basically everywhere will be used rxjs
to handle asynchronous requests, events, calls, and so on. So often used Subject
to process a steady stream of data streams, such as input text change, toast notification and the like.
It must rely on Subject
themselves maybe Observable
also be Observer
, that is subject
either as a 数据源
, can itself become 一组订阅者的代理
.
But when dealing with more complex business needs, simply use Subject
may not meet the requirements, this time to consider rxjs
other offers Subject Class
of, for example BehaviorSubject
ReplaySubject
AsyncSubject
, then we look at them with Subject
what is the difference, what are the characteristics of each, at what time more suitable for use.
[All codes used herein typescript
]
Subject
First we create a Rxjs Subject
type of data isnumber
let subject1: Subject<number> = new Subject<number>(); // (A)
Then we use Subject
the next
method to emit(发射)
a data
subject1.next(100); (B)
Next, subject1
create two subscribers, in subscription
direct printing the received data
subject1.subscribe((res: number) => console.info("subjectA ", res)); // (C) subject1.subscribe((res: number) => console.info("subjectB ", res));
Then I launch two data
subject1.next(200); (D)
subject1.next(300);
Well, let's take a look at what the console which will print out the results.
Perhaps some students will feel the result is that, as Subject
can receive a steady stream of data Well, so no matter how many times the data transmission, the subscriber can receive.
//output
subjectA 100
subjectB 100 subjectA 200 subjectB 200 subjectA 300 subjectB 300
This result is not quite
as Subject
subscriber only after subscription, will receive the data source emits over value.
So in the code block C
, the subscribers in the subscription data source subject1
before, regardless of the code block B
executed many times, subscribers can only receive a code for C之后
data transmission.
The correct result should be:
//output
subjectA 200
subjectB 200 subjectA 300 subjectB 300
This situation often encountered in the project, and sometimes I obviously transmit data from a data source, but the value of it is to get subscribers undefined
, or null
, and this is because subscribers are created after launching a data source, they can not the received data.
If we want to create after the subscribers, no matter what time can get the data, it should be how to do it? It would have to consider the use BehaviourSubject
of.
BehaviorSubject
We still use the earlier example, create a BehaviorSubject
default value is set to 0. BehaviorSubject需要给个默认值
Then a data transmitter 100, to create a subscriber, then a data transmitter 200, and then create a subscriber, the last piece of data transmitter 300.
code show as below:
let subject2: BehaviorSubject<number> = new BehaviorSubject<number>(0); subject2.next(100); subject2.subscribe((res: number) => console.info("behavior-subjectA ", res)); subject2.next(200); subject2.subscribe((res: number) => console.info("behavior-subjectB ", res)); subject2.next(300);
This time the result should be:
//output
behavior-subjectA 100
behavior-subjectA 200
behavior-subjectB 200
behavior-subjectA 300 behavior-subjectB 300
Because BehaviorSubject
that can be stored 最后一条数据
or 初始默认值
, so no matter what time subscribers to subscribe to a data source subject2
, the data can be received.
So for subscribers behavior-subjectA
, who subscribe to when the last data stream data 100
, he immediately received. Then turn can receive the latest data 200
and 300
.
For subscribers behavior-subjectB
, who subscribe to when the last data stream data 200
, he immediately received. Only then you can receive the latest data 300
up.
BehaviorSubject
Give us convenience is that whenever a subscription to a data source can always get the latest or the original data, but can only get 一条数据
, but when we deal with input text change
an event, you need to get all the characters entered by the user, also it is that all the data streams, BehaviorSubject
can not do anything, and this time we consider ReplaySubject
the.
ReplaySubject
We still use the earlier example, create a ReplaySubject
, two transmit data 100 and 200, to create a subscriber, then a data transmitter 300, and then create a subscriber, the last piece of data transmitter 400.
code show as below:
let subject3: ReplaySubject<number> = new ReplaySubject<number>();
subject3.next(100); subject3.next(200); subject3.subscribe((res: number) => console.info("replay-subjectA ", res)); subject3.next(300); subject3.subscribe((res: number) => console.info("replay-subjectB ", res)); subject3.next(400);
Control the printing result will be:
//output
replay-subjectA 100
replay-subjectA 200
replay-subjectA 300
replay-subjectB 100 replay-subjectB 200 replay-subjectB 300 replay-subjectA 400 replay-subjectB 400
ReplaySubject
Is stored in the data stream 所有数据
, 无论何时
subscribe to subject3
, subscribers can get all the data before the subscription data stream, and then still get new data acquisition to the next.
Like ReplaySubject
the class name Replay
, once subscribed to a data source, the data will flow like a movie re-release it again to put to you.
Subscribers replay-subjectA
subscribe to subject3
when the data stream has been 100 and 200, receive and print out.
Finally, the print data 300 and 400. The new
subscriber replay-subjectB
is subscribed to subject3
when the data stream has been 100,200,300, receive and print out. Finally, new print data 400.
Then we must say that this last Subject, that is,AsyncSubject
AsyncSubject
AsyncSubject
And BehaviorSubject
` ReplaySubject
` somewhat similar, but the difference is AsyncSubject
only stored 数据流里的最后一条数据
, but only in 数据流complete时才会将值发布出去
. AsyncSubject
Mainly for handling asynchronous operation, when the data source is asynchronous request processing or event, may emit a lot of data, if we only want to asynchronous operation is completed when the data source, subscribers will receive the value of this time we can use AsyncSubject
the.
Next we look at an example,
create a AsyncSubject
, then transmit data, creating a subscriber, and then transmit the data. . .
let subject4: AsyncSubject<number> = new AsyncSubject<number>();
subject4.next(100); subject4.next(100); subject4.subscribe((res: number) => console.info("async-subjectA ", res)); subject4.next(300); subject4.subscribe((res: number) => console.info("async-subjectB ", res)); subject4.next(400); subject4.subscribe((res: number) => console.info("async-subjectC ", res)); subject4.complete(); subject4.subscribe((res: number) => console.info("async-subjectD ", res)); subject4.next(500);
The final result should be:
//output4
async-subjectA 400
async-subjectB 400 async-subjectC 400 async-subjectD 400
Because subject4
Shi AsyncSubject
, only complete
time will to subscriber publish
data, and only publish
the last data, regardless of when the subscriber subscription data sources, can receive the final data.
But why not print out 500
of it, because the data source already complete
, you can no longer transmit the new data.
to sum up
Finally, to sum up four kinds of Subject
features, a good understanding of their own characteristics, in project development can handle many difficult demands, but also to avoid a lot of problems.