1
1
import { shareLatest } from "@react-rxjs/core"
2
2
import {
3
- defer ,
4
3
GroupedObservable ,
5
4
identity ,
6
5
noop ,
7
6
Observable ,
8
7
Subject ,
9
8
Subscription ,
10
9
} from "rxjs"
11
- import { finalize , map } from "rxjs/operators"
10
+ import { map } from "rxjs/operators"
12
11
13
12
export interface KeyChanges < K > {
14
13
type : "add" | "remove"
@@ -59,23 +58,55 @@ export function partitionByKey<T, K, R>(
59
58
const groups : Map < K , InnerGroup < T , K , R > > = new Map ( )
60
59
61
60
let sourceCompleted = false
61
+ const finalize =
62
+ ( type : "error" | "complete" ) =>
63
+ ( ...args : any [ ] ) => {
64
+ sourceCompleted = true
65
+ if ( groups . size ) {
66
+ groups . forEach ( ( g ) => ( g . source [ type ] as any ) ( ...args ) )
67
+ } else {
68
+ subscriber [ type ] ( ...args )
69
+ }
70
+ }
71
+
62
72
const sub = stream . subscribe (
63
73
( x ) => {
64
74
const key = keySelector ( x )
65
- if ( groups . has ( key ) ) {
66
- return groups . get ( key ) ! . source . next ( x )
75
+ if ( groups . has ( key ) ) return groups . get ( key ) ! . source . next ( x )
76
+
77
+ let pendingFirstAdd = true
78
+ const emitFirstAdd = ( ) => {
79
+ if ( pendingFirstAdd ) {
80
+ pendingFirstAdd = false
81
+ subscriber . next ( {
82
+ groups,
83
+ changes : {
84
+ type : "add" ,
85
+ keys : [ key ] ,
86
+ } ,
87
+ } )
88
+ }
67
89
}
68
90
69
91
const subject = new Subject < T > ( )
92
+ let pendingFirstVal = true
93
+ const emitFirstValue = ( ) => {
94
+ if ( pendingFirstVal ) {
95
+ pendingFirstVal = false
96
+ subject . next ( x )
97
+ }
98
+ }
70
99
71
100
const shared$ = shareLatest ( ) (
72
101
( streamSelector || identity ) ( subject , key ) ,
73
102
)
74
-
75
- const res = defer ( ( ) => {
103
+ const res = new Observable ( ( observer ) => {
76
104
incRefcount ( )
77
- return shared$
78
- } ) . pipe ( finalize ( ( ) => decRefcount ( ) ) ) as any as GroupedObservable < K , R >
105
+ const subscription = shared$ . subscribe ( observer )
106
+ subscription . add ( decRefcount )
107
+ emitFirstValue ( )
108
+ return subscription
109
+ } ) as any as GroupedObservable < K , R >
79
110
; ( res as any ) . key = key
80
111
81
112
const innerGroup : InnerGroup < T , K , R > = {
@@ -85,19 +116,12 @@ export function partitionByKey<T, K, R>(
85
116
}
86
117
groups . set ( key , innerGroup )
87
118
88
- subscriber . next ( {
89
- groups,
90
- changes : {
91
- type : "add" ,
92
- keys : [ key ] ,
93
- } ,
94
- } )
95
-
96
119
innerGroup . subscription = shared$ . subscribe (
97
120
noop ,
98
121
( e ) => subscriber . error ( e ) ,
99
122
( ) => {
100
123
groups . delete ( key )
124
+ emitFirstAdd ( )
101
125
subscriber . next ( {
102
126
groups,
103
127
changes : {
@@ -111,24 +135,11 @@ export function partitionByKey<T, K, R>(
111
135
}
112
136
} ,
113
137
)
114
- subject . next ( x )
115
- } ,
116
- ( e ) => {
117
- sourceCompleted = true
118
- if ( groups . size ) {
119
- groups . forEach ( ( g ) => g . source . error ( e ) )
120
- } else {
121
- subscriber . error ( e )
122
- }
123
- } ,
124
- ( ) => {
125
- sourceCompleted = true
126
- if ( groups . size ) {
127
- groups . forEach ( ( g ) => g . source . complete ( ) )
128
- } else {
129
- subscriber . complete ( )
130
- }
138
+ emitFirstAdd ( )
139
+ emitFirstValue ( )
131
140
} ,
141
+ finalize ( "error" ) ,
142
+ finalize ( "complete" ) ,
132
143
)
133
144
134
145
return ( ) => {
0 commit comments