Skip to content

Commit bc359c9

Browse files
authored
Merge pull request #4476 from reduxjs/feature/listeners-map
2 parents 3dd8082 + 1599aad commit bc359c9

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

src/createStore.ts

+13-10
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import {
66
StoreEnhancer,
77
Dispatch,
88
Observer,
9-
ExtendState
9+
ExtendState,
10+
ListenerCallback
1011
} from './types/store'
1112
import { Action } from './types/actions'
1213
import { Reducer } from './types/reducers'
@@ -119,8 +120,9 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
119120

120121
let currentReducer = reducer
121122
let currentState = preloadedState as S
122-
let currentListeners: (() => void)[] | null = []
123+
let currentListeners: Map<number, ListenerCallback> | null = new Map()
123124
let nextListeners = currentListeners
125+
let listenerIdCounter = 0
124126
let isDispatching = false
125127

126128
/**
@@ -132,7 +134,10 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
132134
*/
133135
function ensureCanMutateNextListeners() {
134136
if (nextListeners === currentListeners) {
135-
nextListeners = currentListeners.slice()
137+
nextListeners = new Map()
138+
currentListeners.forEach((listener, key) => {
139+
nextListeners.set(key, listener)
140+
})
136141
}
137142
}
138143

@@ -197,7 +202,8 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
197202
let isSubscribed = true
198203

199204
ensureCanMutateNextListeners()
200-
nextListeners.push(listener)
205+
const listenerId = listenerIdCounter++
206+
nextListeners.set(listenerId, listener)
201207

202208
return function unsubscribe() {
203209
if (!isSubscribed) {
@@ -214,8 +220,7 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
214220
isSubscribed = false
215221

216222
ensureCanMutateNextListeners()
217-
const index = nextListeners.indexOf(listener)
218-
nextListeners.splice(index, 1)
223+
nextListeners.delete(listenerId)
219224
currentListeners = null
220225
}
221226
}
@@ -272,11 +277,9 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
272277
}
273278

274279
const listeners = (currentListeners = nextListeners)
275-
for (let i = 0; i < listeners.length; i++) {
276-
const listener = listeners[i]
280+
listeners.forEach(listener => {
277281
listener()
278-
}
279-
282+
})
280283
return action
281284
}
282285

src/types/store.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ export interface Unsubscribe {
9191
(): void
9292
}
9393

94+
export type ListenerCallback = () => void
95+
9496
declare global {
9597
interface SymbolConstructor {
9698
readonly observable: symbol
@@ -198,7 +200,7 @@ export interface Store<
198200
* @param listener A callback to be invoked on every dispatch.
199201
* @returns A function to remove this change listener.
200202
*/
201-
subscribe(listener: () => void): Unsubscribe
203+
subscribe(listener: ListenerCallback): Unsubscribe
202204

203205
/**
204206
* Replaces the reducer currently used by the store to calculate the state.

0 commit comments

Comments
 (0)