@@ -9,9 +9,42 @@ import {IObserver} from '../lib/Observer'
9
9
import { IScheduler } from '../lib/Scheduler'
10
10
import { CompositeSubscription , ISubscription } from '../lib/Subscription'
11
11
import { curry } from '../lib/Utils'
12
+ import { just } from '../sources/Create'
12
13
13
14
export type Project < T , S > = ( t : T ) => IObservable < S >
14
15
16
+ // prettier-ignore
17
+ export type mergeMapFunctionWithConcurrency = {
18
+ < T , S > ( concurrency : IObservable < number > , project : Project < T , S > , source : IObservable < T > ) : IObservable < S >
19
+ < T , S > ( concurrency : IObservable < number > ) : { ( project : Project < T , S > , source : IObservable < T > ) : IObservable < S > }
20
+ < T , S > ( concurrency : IObservable < number > ) : { ( project : Project < T , S > ) : { ( source : IObservable < T > ) : IObservable < S > } }
21
+ }
22
+
23
+ // prettier-ignore
24
+ export type mergeMapFunction = {
25
+ < T , S > ( project : Project < T , S > , source : IObservable < T > ) : IObservable < S >
26
+ < T , S > ( project : Project < T , S > , source : IObservable < T > ) : IObservable < S >
27
+ < T , S > ( project : Project < T , S > ) : { ( source : IObservable < T > ) : IObservable < S > }
28
+ }
29
+ // prettier-ignore
30
+ export type joinFunction = < T > ( source : IObservable < IObservable < T > > ) => IObservable < T >
31
+
32
+ class ConcurrencyObserver extends ErrorMixin ( Virgin )
33
+ implements IObserver < number > {
34
+ constructor (
35
+ private outer : MergeMapOuterObserver < any , any > ,
36
+ readonly sink : IObserver < any >
37
+ ) {
38
+ super ( )
39
+ }
40
+
41
+ next ( val : number ) : void {
42
+ this . outer . setConc ( val )
43
+ }
44
+
45
+ complete ( ) : void { }
46
+ }
47
+
15
48
class MergeMapInnerObserver < T , S > implements IObserver < S > {
16
49
node : LinkedListNode < ISubscription >
17
50
@@ -39,27 +72,43 @@ class MergeMapOuterObserver<T, S> extends ErrorMixin(Virgin)
39
72
implements IObserver < T > {
40
73
private __completed : boolean = false
41
74
private __buffer : T [ ] = [ ]
75
+ private __conc = 0
76
+ readonly cSub = new CompositeSubscription ( )
42
77
43
78
constructor (
44
- readonly conc : number ,
79
+ conc : IObservable < number > ,
45
80
readonly proj : Project < T , S > ,
46
81
readonly sink : IObserver < S > ,
47
- readonly cSub : CompositeSubscription ,
48
82
readonly sh : IScheduler
49
83
) {
50
84
super ( )
85
+ conc . subscribe ( new ConcurrencyObserver ( this , sink ) , sh )
86
+ }
87
+
88
+ private getSpace ( ) {
89
+ return this . __conc - this . cSub . length ( )
90
+ }
91
+
92
+ private subscribeNew ( ) {
93
+ while ( this . __buffer . length > 0 && this . getSpace ( ) > 0 ) {
94
+ this . next ( this . __buffer . shift ( ) as T )
95
+ }
96
+ }
97
+
98
+ private unsubscribeOld ( ) {
99
+ while ( this . getSpace ( ) < 0 ) {
100
+ this . cSub . remove ( this . cSub . head ( ) )
101
+ }
51
102
}
52
103
53
104
next ( val : T ) : void {
54
- if ( this . cSub . length ( ) < this . conc + 1 ) {
105
+ if ( this . getSpace ( ) > 0 ) {
55
106
const innerObserver = new MergeMapInnerObserver ( this )
56
107
const node = this . cSub . add (
57
108
this . proj ( val ) . subscribe ( innerObserver , this . sh )
58
109
)
59
110
innerObserver . setup ( node )
60
- } else {
61
- this . __buffer . push ( val )
62
- }
111
+ } else this . __buffer . push ( val )
63
112
}
64
113
65
114
complete ( ) : void {
@@ -68,61 +117,50 @@ class MergeMapOuterObserver<T, S> extends ErrorMixin(Virgin)
68
117
}
69
118
70
119
checkComplete ( ) {
71
- if ( this . __completed && this . cSub . length ( ) === 1 ) this . sink . complete ( )
72
- else if ( this . __buffer . length > 0 ) {
73
- if ( this . __buffer . length > 0 ) {
74
- this . next ( this . __buffer . shift ( ) as T )
75
- }
76
- }
120
+ if (
121
+ this . __completed &&
122
+ this . cSub . length ( ) === 0 &&
123
+ this . __buffer . length === 0
124
+ )
125
+ this . sink . complete ( )
126
+ else this . subscribeNew ( )
127
+ }
128
+
129
+ setConc ( value : number ) {
130
+ this . __conc = value
131
+ const space = this . getSpace ( )
132
+ if ( space > 0 ) this . subscribeNew ( )
133
+ else if ( space < 0 ) this . unsubscribeOld ( )
77
134
}
78
135
}
79
136
80
137
class MergeMap < T , S > implements IObservable < S > {
81
138
constructor (
82
- private conc : number ,
139
+ private conc : IObservable < number > ,
83
140
private proj : Project < T , S > ,
84
141
private src : IObservable < T >
85
142
) { }
86
143
87
144
subscribe ( observer : IObserver < S > , scheduler : IScheduler ) : ISubscription {
88
145
const cSub = new CompositeSubscription ( )
89
- const outerObserver = new MergeMapOuterObserver < T , S > (
90
- this . conc ,
91
- this . proj ,
92
- observer ,
93
- cSub ,
94
- scheduler
95
- )
146
+
147
+ // prettier-ignore
148
+ const outerObserver = new MergeMapOuterObserver < T , S > ( this . conc , this . proj , observer , scheduler )
149
+ cSub . add ( outerObserver . cSub )
96
150
cSub . add ( this . src . subscribe ( outerObserver , scheduler ) )
97
151
return cSub
98
152
}
99
153
}
100
154
101
- // prettier-ignore
102
- export type mergeMapFunctionWithConcurrency = {
103
- < T , S > ( concurrency : number , project : Project < T , S > , source : IObservable < T > ) : IObservable < S >
104
- < T , S > ( concurrency : number ) : { ( project : Project < T , S > , source : IObservable < T > ) : IObservable < S > }
105
- < T , S > ( concurrency : number ) : { ( project : Project < T , S > ) : { ( source : IObservable < T > ) : IObservable < S > } }
106
- }
107
-
108
- // prettier-ignore
109
- export type mergeMapFunction = {
110
- < T , S > ( project : Project < T , S > , source : IObservable < T > ) : IObservable < S >
111
- < T , S > ( project : Project < T , S > , source : IObservable < T > ) : IObservable < S >
112
- < T , S > ( project : Project < T , S > ) : { ( source : IObservable < T > ) : IObservable < S > }
113
- }
114
-
115
- export type joinFunction = < T > (
116
- source : IObservable < IObservable < T > >
117
- ) => IObservable < T >
118
-
119
155
export const mergeMap : mergeMapFunctionWithConcurrency = curry (
120
156
< T , S > (
121
- concurrency : number ,
157
+ concurrency : IObservable < number > ,
122
158
project : Project < T , S > ,
123
159
source : IObservable < T >
124
160
) : IObservable < S > => new MergeMap ( concurrency , project , source )
125
161
)
126
- export const flatMap = mergeMap ( Number . POSITIVE_INFINITY ) as mergeMapFunction
127
- export const concatMap : mergeMapFunction = mergeMap ( 1 ) as mergeMapFunction
162
+ export const flatMap = mergeMap (
163
+ just ( Number . POSITIVE_INFINITY )
164
+ ) as mergeMapFunction
165
+ export const concatMap : mergeMapFunction = mergeMap ( just ( 1 ) ) as mergeMapFunction
128
166
export const join = flatMap ( i => i ) as joinFunction
0 commit comments