1
1
import { Observable } from '../Observable' ;
2
+ import { innerFrom } from '../observable/from' ;
2
3
import { Subject } from '../Subject' ;
3
- import { Observer , OperatorFunction } from '../types' ;
4
+ import { ObservableInput , Observer , OperatorFunction , SubjectLike } from '../types' ;
4
5
import { operate } from '../util/lift' ;
5
6
import { OperatorSubscriber } from './OperatorSubscriber' ;
6
7
8
+ interface BasicGroupByOptions < K , T > {
9
+ element ?: undefined ;
10
+ duration ?: ( grouped : GroupedObservable < K , T > ) => ObservableInput < any > ;
11
+ connector ?: ( ) => SubjectLike < T > ;
12
+ }
13
+
14
+ interface GroupByOptionsWithElement < K , E , T > {
15
+ element : ( value : T ) => E ;
16
+ duration ?: ( grouped : GroupedObservable < K , E > ) => ObservableInput < any > ;
17
+ connector ?: ( ) => SubjectLike < E > ;
18
+ }
19
+
20
+ export function groupBy < T , K > ( key : ( value : T ) => K , options : BasicGroupByOptions < K , T > ) : OperatorFunction < T , GroupedObservable < K , T > > ;
21
+
22
+ export function groupBy < T , K , E > (
23
+ key : ( value : T ) => K ,
24
+ options : GroupByOptionsWithElement < K , E , T >
25
+ ) : OperatorFunction < T , GroupedObservable < K , E > > ;
26
+
7
27
export function groupBy < T , K extends T > (
8
- keySelector : ( value : T ) => value is K
28
+ key : ( value : T ) => value is K
9
29
) : OperatorFunction < T , GroupedObservable < true , K > | GroupedObservable < false , Exclude < T , K > > > ;
10
- export function groupBy < T , K > ( keySelector : ( value : T ) => K ) : OperatorFunction < T , GroupedObservable < K , T > > ;
30
+
31
+ export function groupBy < T , K > ( key : ( value : T ) => K ) : OperatorFunction < T , GroupedObservable < K , T > > ;
32
+
33
+ /**
34
+ * @deprecated use the options parameter instead.
35
+ */
11
36
export function groupBy < T , K > (
12
- keySelector : ( value : T ) => K ,
13
- elementSelector : void ,
14
- durationSelector : ( grouped : GroupedObservable < K , T > ) => Observable < any >
37
+ key : ( value : T ) => K ,
38
+ element : void ,
39
+ duration : ( grouped : GroupedObservable < K , T > ) => Observable < any >
15
40
) : OperatorFunction < T , GroupedObservable < K , T > > ;
41
+
42
+ /**
43
+ * @deprecated use the options parameter instead.
44
+ */
16
45
export function groupBy < T , K , R > (
17
- keySelector : ( value : T ) => K ,
18
- elementSelector ?: ( value : T ) => R ,
19
- durationSelector ?: ( grouped : GroupedObservable < K , R > ) => Observable < any >
20
- ) : OperatorFunction < T , GroupedObservable < K , R > > ;
21
- export function groupBy < T , K , R > (
22
- keySelector : ( value : T ) => K ,
23
- elementSelector ?: ( value : T ) => R ,
24
- durationSelector ?: ( grouped : GroupedObservable < K , R > ) => Observable < any > ,
25
- subjectSelector ?: ( ) => Subject < R >
46
+ key : ( value : T ) => K ,
47
+ element ?: ( value : T ) => R ,
48
+ duration ?: ( grouped : GroupedObservable < K , R > ) => Observable < any >
26
49
) : OperatorFunction < T , GroupedObservable < K , R > > ;
27
50
28
51
/**
@@ -32,7 +55,7 @@ export function groupBy<T, K, R>(
32
55
*
33
56
* 
34
57
*
35
- * When the Observable emits an item, a key is computed for this item with the keySelector function.
58
+ * When the Observable emits an item, a key is computed for this item with the key function.
36
59
*
37
60
* If a {@link GroupedObservable} for this key exists, this {@link GroupedObservable} emits. Otherwise, a new
38
61
* {@link GroupedObservable} for this key is created and emits.
@@ -41,7 +64,7 @@ export function groupBy<T, K, R>(
41
64
* key is available as the `key` field of a {@link GroupedObservable} instance.
42
65
*
43
66
* The elements emitted by {@link GroupedObservable}s are by default the items emitted by the Observable, or elements
44
- * returned by the elementSelector function.
67
+ * returned by the element function.
45
68
*
46
69
* ## Examples
47
70
*
@@ -101,28 +124,45 @@ export function groupBy<T, K, R>(
101
124
* // { id: 3, values: [ 'TSLint' ] }
102
125
* ```
103
126
*
104
- * @param { function(value: T): K } keySelector A function that extracts the key
127
+ * @param key A function that extracts the key
105
128
* for each item.
106
- * @param { function(value: T): R } [elementSelector] A function that extracts the
129
+ * @param element A function that extracts the
107
130
* return element for each item.
108
- * @param { function(grouped: GroupedObservable<K,R>): Observable<any> } [durationSelector]
131
+ * @param duration
109
132
* A function that returns an Observable to determine how long each group should
110
133
* exist.
111
- * @param { function(): Subject<R> } [subjectSelector] Factory function to create an
134
+ * @param connector Factory function to create an
112
135
* intermediate Subject through which grouped elements are emitted.
113
136
* @return A function that returns an Observable that emits GroupedObservables,
114
137
* each of which corresponds to a unique key value and each of which emits
115
138
* those items from the source Observable that share that key value.
139
+ *
140
+ * @deprecated Use the options parameter instead.
116
141
*/
142
+ export function groupBy < T , K , R > (
143
+ key : ( value : T ) => K ,
144
+ element ?: ( value : T ) => R ,
145
+ duration ?: ( grouped : GroupedObservable < K , R > ) => Observable < any > ,
146
+ connector ?: ( ) => Subject < R >
147
+ ) : OperatorFunction < T , GroupedObservable < K , R > > ;
148
+
149
+ // Impl
117
150
export function groupBy < T , K , R > (
118
151
keySelector : ( value : T ) => K ,
119
- elementSelector ?: ( ( value : T ) => R ) | void ,
120
- durationSelector ?: ( grouped : GroupedObservable < K , R > ) => Observable < any > ,
121
- subjectSelector ?: ( ) => Subject < R >
152
+ elementOrOptions ?: ( ( value : any ) => any ) | void | BasicGroupByOptions < K , T > | GroupByOptionsWithElement < K , R , T > ,
153
+ duration ?: ( grouped : GroupedObservable < any , any > ) => ObservableInput < any > ,
154
+ connector ?: ( ) => SubjectLike < any >
122
155
) : OperatorFunction < T , GroupedObservable < K , R > > {
123
156
return operate ( ( source , subscriber ) => {
157
+ let element : ( ( value : any ) => any ) | void ;
158
+ if ( ! elementOrOptions || typeof elementOrOptions === 'function' ) {
159
+ element = elementOrOptions ;
160
+ } else {
161
+ ( { duration, element, connector } = elementOrOptions ) ;
162
+ }
163
+
124
164
// A lookup for the groups that we have so far.
125
- const groups = new Map < K , Subject < any > > ( ) ;
165
+ const groups = new Map < K , SubjectLike < any > > ( ) ;
126
166
127
167
// Used for notifying all groups and the subscriber in the same way.
128
168
const notify = ( cb : ( group : Observer < any > ) => void ) => {
@@ -153,15 +193,15 @@ export function groupBy<T, K, R>(
153
193
let group = groups . get ( key ) ;
154
194
if ( ! group ) {
155
195
// Create our group subject
156
- groups . set ( key , ( group = subjectSelector ? subjectSelector ( ) : new Subject < any > ( ) ) ) ;
196
+ groups . set ( key , ( group = connector ? connector ( ) : new Subject < any > ( ) ) ) ;
157
197
158
198
// Emit the grouped observable. Note that we can't do a simple `asObservable()` here,
159
199
// because the grouped observable has special semantics around reference counting
160
200
// to ensure we don't sever our connection to the source prematurely.
161
201
const grouped = createGroupedObservable ( key , group ) ;
162
202
subscriber . next ( grouped ) ;
163
203
164
- if ( durationSelector ) {
204
+ if ( duration ) {
165
205
const durationSubscriber = new OperatorSubscriber (
166
206
// Providing the group here ensures that it is disposed of -- via `unsubscribe` --
167
207
// wnen the duration subscription is torn down. That is important, because then
@@ -185,12 +225,12 @@ export function groupBy<T, K, R>(
185
225
) ;
186
226
187
227
// Start our duration notifier.
188
- groupBySourceSubscriber . add ( durationSelector ( grouped ) . subscribe ( durationSubscriber ) ) ;
228
+ groupBySourceSubscriber . add ( innerFrom ( duration ( grouped ) ) . subscribe ( durationSubscriber ) ) ;
189
229
}
190
230
}
191
231
192
232
// Send the value to our group.
193
- group . next ( elementSelector ? elementSelector ( value ) : value ) ;
233
+ group . next ( element ? element ( value ) : value ) ;
194
234
} catch ( err ) {
195
235
handleError ( err ) ;
196
236
}
@@ -214,7 +254,7 @@ export function groupBy<T, K, R>(
214
254
* @param key The key of the group
215
255
* @param groupSubject The subject that fuels the group
216
256
*/
217
- function createGroupedObservable ( key : K , groupSubject : Subject < any > ) {
257
+ function createGroupedObservable ( key : K , groupSubject : SubjectLike < any > ) {
218
258
const result : any = new Observable < T > ( ( groupSubscriber ) => {
219
259
groupBySourceSubscriber . activeGroups ++ ;
220
260
const innerSub = groupSubject . subscribe ( groupSubscriber ) ;
0 commit comments