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
94
95
96
97
98 |
1
1
1
1
1
14
14
14
1
14
1
1
14
14
14
1
14
14
14
14
14
3
1
1
98
98
98
98
83
83
83
1
82
82
15
1
82
4
78
78
1
14
14
3
1
74
74
74
74
15
74
9
1
60
1 | import {Operator} from '../Operator';
import {Observable} from '../Observable';
import {Scheduler} from '../Scheduler';
import {Subscriber} from '../Subscriber';
import {tryCatch} from '../util/tryCatch';
import {errorObject} from '../util/errorObject';
import {OuterSubscriber} from '../OuterSubscriber';
import {InnerSubscriber} from '../InnerSubscriber';
import {subscribeToResult} from '../util/subscribeToResult';
export class ExpandOperator<T, R> implements Operator<T, R> {
constructor(private project: (value: T, index: number) => Observable<R>,
private concurrent: number,
private scheduler: Scheduler) {
}
call(subscriber: Subscriber<R>): Subscriber<T> {
return new ExpandSubscriber(subscriber, this.project, this.concurrent, this.scheduler);
}
}
export class ExpandSubscriber<T, R> extends OuterSubscriber<T, R> {
private index: number = 0;
private active: number = 0;
private hasCompleted: boolean = false;
private buffer: any[];
constructor(destination: Subscriber<R>,
private project: (value: T, index: number) => Observable<R>,
private concurrent: number,
private scheduler: Scheduler) {
super(destination);
if (concurrent < Number.POSITIVE_INFINITY) {
this.buffer = [];
}
}
private static dispatch({subscriber, result, value, index}): void {
subscriber.subscribeToProjection(result, value, index);
}
_next(value: any): void {
const destination = this.destination;
Iif (destination.isUnsubscribed) {
this._complete();
return;
}
const index = this.index++;
if (this.active < this.concurrent) {
destination.next(value);
let result = tryCatch(this.project)(value, index);
if (result === errorObject) {
destination.error(result.e);
} else Eif (!this.scheduler) {
this.subscribeToProjection(result, value, index);
} else {
const state = { subscriber: this, result, value, index };
this.add(this.scheduler.schedule(ExpandSubscriber.dispatch, 0, state));
}
} else {
this.buffer.push(value);
}
}
private subscribeToProjection(result, value: T, index: number): void {
if (result._isScalar) {
this._next(result.value);
} else {
this.active++;
this.add(subscribeToResult<T, R>(this, result, value, index));
}
}
_complete(): void {
this.hasCompleted = true;
if (this.hasCompleted && this.active === 0) {
this.destination.complete();
}
}
notifyComplete(innerSub?: InnerSubscriber<T, R>): void {
const buffer = this.buffer;
this.remove(innerSub);
this.active--;
if (buffer && buffer.length > 0) {
this._next(buffer.shift());
}
if (this.hasCompleted && this.active === 0) {
this.destination.complete();
}
}
notifyNext(outerValue: T, innerValue: R, outerIndex: number, innerIndex: number): void {
this._next(innerValue);
}
} |