forked from ReactiveX/rxjs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
repeat.ts
93 lines (91 loc) · 2.76 KB
/
repeat.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { Subscription } from '../Subscription';
import { EMPTY } from '../observable/empty';
import { operate } from '../util/lift';
import { MonoTypeOperatorFunction } from '../types';
import { OperatorSubscriber } from './OperatorSubscriber';
/**
* Returns an Observable that will resubscribe to the source stream when the source stream completes, at most count times.
*
* <span class="informal">Repeats all values emitted on the source. It's like {@link retry}, but for non error cases.</span>
*
* ![](repeat.png)
*
* Similar to {@link retry}, this operator repeats the stream of items emitted by the source for non error cases.
* Repeat can be useful for creating observables that are meant to have some repeated pattern or rhythm.
*
* Note: `repeat(0)` returns an empty observable and `repeat()` will repeat forever
*
* ## Example
* Repeat a message stream
* ```ts
* import { of } from 'rxjs';
* import { repeat } from 'rxjs/operators';
*
* const source = of('Repeat message');
* const example = source.pipe(repeat(3));
* example.subscribe(x => console.log(x));
*
* // Results
* // Repeat message
* // Repeat message
* // Repeat message
* ```
*
* Repeat 3 values, 2 times
* ```ts
* import { interval } from 'rxjs';
* import { repeat, take } from 'rxjs/operators';
*
* const source = interval(1000);
* const example = source.pipe(take(3), repeat(2));
* example.subscribe(x => console.log(x));
*
* // Results every second
* // 0
* // 1
* // 2
* // 0
* // 1
* // 2
* ```
*
* @see {@link repeatWhen}
* @see {@link retry}
*
* @param {number} [count] The number of times the source Observable items are repeated, a count of 0 will yield
* an empty Observable.
* @return A function that returns an Observable that will resubscribe to the
* source stream when the source stream completes, at most `count` times.
*/
export function repeat<T>(count = Infinity): MonoTypeOperatorFunction<T> {
return count <= 0
? () => EMPTY
: operate((source, subscriber) => {
let soFar = 0;
let innerSub: Subscription | null;
const subscribeForRepeat = () => {
let syncUnsub = false;
innerSub = source.subscribe(
new OperatorSubscriber(subscriber, undefined, () => {
if (++soFar < count) {
if (innerSub) {
innerSub.unsubscribe();
innerSub = null;
subscribeForRepeat();
} else {
syncUnsub = true;
}
} else {
subscriber.complete();
}
})
);
if (syncUnsub) {
innerSub.unsubscribe();
innerSub = null;
subscribeForRepeat();
}
};
subscribeForRepeat();
});
}