1
+ import { Operator } from '../Operator' ;
2
+ import { Subscriber } from '../Subscriber' ;
3
+ import { ArgumentOutOfRangeError } from '../util/ArgumentOutOfRangeError' ;
4
+ import { Observable } from '../Observable' ;
5
+ import { TeardownLogic } from '../Subscription' ;
6
+ import { MonoTypeOperatorFunction } from '../interfaces' ;
7
+
8
+ /**
9
+ * Skip the last `count` values emitted by the source Observable.
10
+ *
11
+ * <img src="./img/skipLast.png" width="100%">
12
+ *
13
+ * `skipLast` returns an Observable that accumulates a queue with a length
14
+ * enough to store the first `count` values. As more values are received,
15
+ * values are taken from the front of the queue and produced on the result
16
+ * sequence. This causes values to be delayed.
17
+ *
18
+ * @example <caption>Skip the last 2 values of an Observable with many values</caption>
19
+ * var many = Rx.Observable.range(1, 5);
20
+ * var skipLastTwo = many.skipLast(2);
21
+ * skipLastTwo.subscribe(x => console.log(x));
22
+ *
23
+ * // Results in:
24
+ * // 1 2 3
25
+ *
26
+ * @see {@link skip }
27
+ * @see {@link skipUntil }
28
+ * @see {@link skipWhile }
29
+ * @see {@link take }
30
+ *
31
+ * @throws {ArgumentOutOfRangeError } When using `skipLast(i)`, it throws
32
+ * ArgumentOutOrRangeError if `i < 0`.
33
+ *
34
+ * @param {number } count Number of elements to skip from the end of the source Observable.
35
+ * @returns {Observable<T> } An Observable that skips the last count values
36
+ * emitted by the source Observable.
37
+ * @method skipLast
38
+ * @owner Observable
39
+ */
40
+ export function skipLast < T > ( count : number ) : MonoTypeOperatorFunction < T > {
41
+ return ( source : Observable < T > ) => source . lift ( new SkipLastOperator ( count ) ) ;
42
+ }
43
+
44
+ class SkipLastOperator < T > implements Operator < T , T > {
45
+ constructor ( private _skipCount : number ) {
46
+ if ( this . _skipCount < 0 ) {
47
+ throw new ArgumentOutOfRangeError ;
48
+ }
49
+ }
50
+
51
+ call ( subscriber : Subscriber < T > , source : any ) : TeardownLogic {
52
+ if ( this . _skipCount === 0 ) {
53
+ // If we don't want to skip any values then just subscribe
54
+ // to Subscriber without any further logic.
55
+ return source . subscribe ( new Subscriber ( subscriber ) ) ;
56
+ } else {
57
+ return source . subscribe ( new SkipLastSubscriber ( subscriber , this . _skipCount ) ) ;
58
+ }
59
+ }
60
+ }
61
+
62
+ /**
63
+ * We need this JSDoc comment for affecting ESDoc.
64
+ * @ignore
65
+ * @extends {Ignored }
66
+ */
67
+ class SkipLastSubscriber < T > extends Subscriber < T > {
68
+ private _ring : T [ ] ;
69
+ private _count : number = 0 ;
70
+
71
+ constructor ( destination : Subscriber < T > , private _skipCount : number ) {
72
+ super ( destination ) ;
73
+ this . _ring = new Array < T > ( _skipCount ) ;
74
+ }
75
+
76
+ protected _next ( value : T ) : void {
77
+ const skipCount = this . _skipCount ;
78
+ const count = this . _count ++ ;
79
+
80
+ if ( count < skipCount ) {
81
+ this . _ring [ count ] = value ;
82
+ } else {
83
+ const currentIndex = count % skipCount ;
84
+ const ring = this . _ring ;
85
+ const oldValue = ring [ currentIndex ] ;
86
+
87
+ ring [ currentIndex ] = value ;
88
+ this . destination . next ( oldValue ) ;
89
+ }
90
+ }
91
+ }
0 commit comments