Skip to content

Commit 6ed3421

Browse files
committed
refactor: add subscribable
1 parent 10db6b3 commit 6ed3421

File tree

8 files changed

+61
-99
lines changed

8 files changed

+61
-99
lines changed

src/core/focusManager.ts

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,13 @@
1+
import { Subscribable } from './subscribable'
12
import { isServer } from './utils'
23

3-
type FocusListener = () => void
4-
5-
class FocusManager {
6-
private listeners: FocusListener[]
4+
class FocusManager extends Subscribable {
75
private removeHandler?: () => void
86

9-
constructor() {
10-
this.listeners = []
11-
}
12-
13-
subscribe(listener: FocusListener): () => void {
7+
protected onSubscribe(): void {
148
if (!this.removeHandler) {
159
this.setDefaultHandler()
1610
}
17-
18-
this.listeners.push(listener)
19-
20-
return () => {
21-
this.listeners = this.listeners.filter(x => x === listener)
22-
}
2311
}
2412

2513
setHandler(init: (onFocus: () => void) => () => void): void {

src/core/mutationCache.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ import type { QueryClient } from './queryClient'
33
import { notifyManager } from './notifyManager'
44
import { Mutation, MutationState } from './mutation'
55
import { noop } from './utils'
6+
import { Subscribable } from './subscribable'
67

78
// TYPES
89

910
type MutationCacheListener = (mutation?: Mutation) => void
1011

1112
// CLASS
1213

13-
export class MutationCache {
14-
private listeners: MutationCacheListener[]
14+
export class MutationCache extends Subscribable<MutationCacheListener> {
1515
private mutations: Mutation<any, any, any, any>[]
1616
private mutationId: number
1717

1818
constructor() {
19-
this.listeners = []
19+
super()
2020
this.mutations = []
2121
this.mutationId = 0
2222
}
@@ -63,13 +63,6 @@ export class MutationCache {
6363
return this.mutations
6464
}
6565

66-
subscribe(listener: MutationCacheListener): () => void {
67-
this.listeners.push(listener)
68-
return () => {
69-
this.listeners = this.listeners.filter(x => x !== listener)
70-
}
71-
}
72-
7366
notify(mutation?: Mutation<any, any, any, any>) {
7467
notifyManager.batch(() => {
7568
this.listeners.forEach(listener => {

src/core/mutationObserver.ts

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { getDefaultState, Mutation } from './mutation'
22
import { notifyManager } from './notifyManager'
33
import type { QueryClient } from './queryClient'
4+
import { Subscribable } from './subscribable'
45
import type {
56
MutateOptions,
67
MutationObserverResult,
@@ -21,6 +22,8 @@ export class MutationObserver<
2122
TError = unknown,
2223
TVariables = void,
2324
TContext = unknown
25+
> extends Subscribable<
26+
MutationObserverListener<TData, TError, TVariables, TContext>
2427
> {
2528
options!: MutationObserverOptions<TData, TError, TVariables, TContext>
2629

@@ -32,19 +35,14 @@ export class MutationObserver<
3235
TContext
3336
>
3437
private currentMutation?: Mutation<TData, TError, TVariables, TContext>
35-
private listeners: MutationObserverListener<
36-
TData,
37-
TError,
38-
TVariables,
39-
TContext
40-
>[]
4138

4239
constructor(
4340
client: QueryClient,
4441
options: MutationObserverOptions<TData, TError, TVariables, TContext>
4542
) {
43+
super()
44+
4645
this.client = client
47-
this.listeners = []
4846
this.setOptions(options)
4947

5048
// Bind exposed methods
@@ -61,20 +59,7 @@ export class MutationObserver<
6159
this.options = this.client.defaultMutationOptions(options)
6260
}
6361

64-
subscribe(
65-
listener?: MutationObserverListener<TData, TError, TVariables, TContext>
66-
): () => void {
67-
const callback = listener || (() => undefined)
68-
this.listeners.push(callback)
69-
return () => {
70-
this.unsubscribe(callback)
71-
}
72-
}
73-
74-
private unsubscribe(
75-
listener: MutationObserverListener<TData, TError, TVariables, TContext>
76-
): void {
77-
this.listeners = this.listeners.filter(x => x !== listener)
62+
protected onUnsubscribe(): void {
7863
if (!this.listeners.length) {
7964
this.currentMutation?.removeObserver(this)
8065
}

src/core/onlineManager.ts

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,13 @@
1+
import { Subscribable } from './subscribable'
12
import { isServer } from './utils'
23

3-
type OnlineListener = () => void
4-
5-
class OnlineManager {
6-
private listeners: OnlineListener[]
4+
class OnlineManager extends Subscribable {
75
private removeHandler?: () => void
86

9-
constructor() {
10-
this.listeners = []
11-
}
12-
13-
subscribe(listener: OnlineListener): () => void {
7+
protected onSubscribe(): void {
148
if (!this.removeHandler) {
159
this.setDefaultHandler()
1610
}
17-
18-
this.listeners.push(listener)
19-
20-
return () => {
21-
this.listeners = this.listeners.filter(x => x === listener)
22-
}
2311
}
2412

2513
setHandler(init: (onOnline: () => void) => () => void): void {

src/core/queriesObserver.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,39 @@ import { notifyManager } from './notifyManager'
33
import type { QueryObserverOptions, QueryObserverResult } from './types'
44
import type { QueryClient } from './queryClient'
55
import { QueryObserver } from './queryObserver'
6+
import { Subscribable } from './subscribable'
67

78
type QueriesObserverListener = (result: QueryObserverResult[]) => void
89

9-
export class QueriesObserver {
10+
export class QueriesObserver extends Subscribable<QueriesObserverListener> {
1011
private client: QueryClient
1112
private result: QueryObserverResult[]
1213
private queries: QueryObserverOptions[]
1314
private observers: QueryObserver[]
14-
private listeners: QueriesObserverListener[]
1515

1616
constructor(client: QueryClient, queries?: QueryObserverOptions[]) {
17+
super()
18+
1719
this.client = client
1820
this.queries = queries || []
1921
this.result = []
2022
this.observers = []
21-
this.listeners = []
2223

2324
// Subscribe to queries
2425
this.updateObservers()
2526
}
2627

27-
subscribe(listener?: QueriesObserverListener): () => void {
28-
const callback = listener || (() => undefined)
29-
30-
this.listeners.push(callback)
31-
28+
protected onSubscribe(): void {
3229
if (this.listeners.length === 1) {
3330
this.observers.forEach(observer => {
3431
observer.subscribe(result => {
3532
this.onUpdate(observer, result)
3633
})
3734
})
3835
}
39-
40-
return () => {
41-
this.unsubscribe(callback)
42-
}
4336
}
4437

45-
private unsubscribe(listener: QueriesObserverListener): void {
46-
this.listeners = this.listeners.filter(x => x !== listener)
38+
protected onUnsubscribe(): void {
4739
if (!this.listeners.length) {
4840
this.destroy()
4941
}

src/core/queryCache.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Query, QueryState } from './query'
88
import type { QueryKey, QueryOptions } from './types'
99
import { notifyManager } from './notifyManager'
1010
import type { QueryClient } from './queryClient'
11+
import { Subscribable } from './subscribable'
1112

1213
// TYPES
1314

@@ -19,13 +20,13 @@ type QueryCacheListener = (query?: Query) => void
1920

2021
// CLASS
2122

22-
export class QueryCache {
23-
private listeners: QueryCacheListener[]
23+
export class QueryCache extends Subscribable<QueryCacheListener> {
2424
private queries: Query<any, any>[]
2525
private queriesMap: QueryHashMap
2626

2727
constructor() {
28-
this.listeners = []
28+
super()
29+
2930
this.queries = []
3031
this.queriesMap = {}
3132
}
@@ -108,13 +109,6 @@ export class QueryCache {
108109
: this.queries
109110
}
110111

111-
subscribe(listener: QueryCacheListener): () => void {
112-
this.listeners.push(listener)
113-
return () => {
114-
this.listeners = this.listeners.filter(x => x !== listener)
115-
}
116-
}
117-
118112
notify(query?: Query<any, any>) {
119113
notifyManager.batch(() => {
120114
this.listeners.forEach(listener => {

src/core/queryObserver.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type {
1818
import type { Query, QueryState, Action, FetchOptions } from './query'
1919
import type { QueryClient } from './queryClient'
2020
import { focusManager } from './focusManager'
21+
import { Subscribable } from './subscribable'
2122

2223
type QueryObserverListener<TData, TError> = (
2324
result: QueryObserverResult<TData, TError>
@@ -39,15 +40,14 @@ export class QueryObserver<
3940
TError = unknown,
4041
TQueryFnData = TData,
4142
TQueryData = TQueryFnData
42-
> {
43+
> extends Subscribable<QueryObserverListener<TData, TError>> {
4344
options: QueryObserverOptions<TData, TError, TQueryFnData, TQueryData>
4445

4546
private client: QueryClient
4647
private currentQuery!: Query<TQueryData, TError, TQueryFnData>
4748
private currentResult!: QueryObserverResult<TData, TError>
4849
private currentResultState?: QueryState<TQueryData, TError>
4950
private previousQueryResult?: QueryObserverResult<TData, TError>
50-
private listeners: QueryObserverListener<TData, TError>[]
5151
private initialDataUpdateCount: number
5252
private staleTimeoutId?: number
5353
private refetchIntervalId?: number
@@ -56,9 +56,10 @@ export class QueryObserver<
5656
client: QueryClient,
5757
options: QueryObserverOptions<TData, TError, TQueryFnData, TQueryData>
5858
) {
59+
super()
60+
5961
this.client = client
6062
this.options = options
61-
this.listeners = []
6263
this.initialDataUpdateCount = 0
6364

6465
// Bind exposed methods
@@ -76,11 +77,7 @@ export class QueryObserver<
7677
this.setOptions(options)
7778
}
7879

79-
subscribe(listener?: QueryObserverListener<TData, TError>): () => void {
80-
const callback = listener || (() => undefined)
81-
82-
this.listeners.push(callback)
83-
80+
protected onSubscribe(): void {
8481
if (this.listeners.length === 1) {
8582
this.currentQuery.addObserver(this)
8683

@@ -90,14 +87,9 @@ export class QueryObserver<
9087

9188
this.updateTimers()
9289
}
93-
94-
return () => {
95-
this.unsubscribe(callback)
96-
}
9790
}
9891

99-
private unsubscribe(listener: QueryObserverListener<TData, TError>): void {
100-
this.listeners = this.listeners.filter(x => x !== listener)
92+
protected onUnsubscribe(): void {
10193
if (!this.listeners.length) {
10294
this.destroy()
10395
}

src/core/subscribable.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
type Listener = () => void
2+
3+
export class Subscribable<TListener = Listener> {
4+
protected listeners: TListener[]
5+
6+
constructor() {
7+
this.listeners = []
8+
}
9+
10+
subscribe(listener?: TListener): () => void {
11+
const callback = listener || (() => undefined)
12+
13+
this.listeners.push(callback as TListener)
14+
15+
this.onSubscribe()
16+
17+
return () => {
18+
this.listeners = this.listeners.filter(x => x !== callback)
19+
this.onUnsubscribe()
20+
}
21+
}
22+
23+
protected onSubscribe(): void {
24+
// Do nothing
25+
}
26+
27+
protected onUnsubscribe(): void {
28+
// Do nothing
29+
}
30+
}

0 commit comments

Comments
 (0)