Skip to content

Commit eb5a5ea

Browse files
committed
avoid useless calls to listeners
1 parent cb5a00b commit eb5a5ea

File tree

2 files changed

+46
-13
lines changed

2 files changed

+46
-13
lines changed

src/createStore.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ export default function createStore(reducer, preloadedState, enhancer) {
5858
var currentState = preloadedState
5959
var currentListeners = []
6060
var nextListeners = currentListeners
61+
var listeners = []
62+
var listenerId = 0
6163
var isDispatching = false
6264

6365
function ensureCanMutateNextListeners() {
@@ -140,8 +142,14 @@ export default function createStore(reducer, preloadedState, enhancer) {
140142
isSubscribed = false
141143

142144
ensureCanMutateNextListeners()
143-
var index = nextListeners.indexOf(listener)
145+
let index = nextListeners.indexOf(listener)
144146
nextListeners.splice(index, 1)
147+
148+
index = listeners.indexOf(listener)
149+
if (index !== -1 && index > listenerId) {
150+
listener()
151+
listeners.splice(index, 1)
152+
}
145153
}
146154
}
147155

@@ -196,10 +204,13 @@ export default function createStore(reducer, preloadedState, enhancer) {
196204
isDispatching = false
197205
}
198206

199-
var listeners = currentListeners = nextListeners
200-
for (var i = 0; i < listeners.length; i++) {
201-
listeners[i]()
207+
listeners = currentListeners = nextListeners
208+
for (listenerId = 0; listenerId < listeners.length; listenerId++) {
209+
listeners[listenerId]()
202210
}
211+
currentListeners = nextListeners
212+
listeners = []
213+
listenerId = 0
203214

204215
return action
205216
}

test/createStore.spec.js

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import expect from 'expect'
22
import { createStore, combineReducers } from '../src/index'
3-
import {
4-
addTodo,
5-
dispatchInMiddle,
3+
import {
4+
addTodo,
5+
dispatchInMiddle,
66
getStateInMiddle,
77
subscribeInMiddle,
88
unsubscribeInMiddle,
9-
throwError,
10-
unknownAction
9+
throwError,
10+
unknownAction
1111
} from './helpers/actionCreators'
1212
import * as reducers from './helpers/reducers'
1313
import * as Rx from 'rxjs'
@@ -388,18 +388,40 @@ describe('createStore', () => {
388388

389389
store.dispatch(unknownAction())
390390
expect(listener1.calls.length).toBe(1)
391-
expect(listener2.calls.length).toBe(2)
392-
expect(listener3.calls.length).toBe(2)
391+
expect(listener2.calls.length).toBe(1)
392+
expect(listener3.calls.length).toBe(1)
393393
expect(listener4.calls.length).toBe(1)
394394

395395
unsubscribe4()
396396
store.dispatch(unknownAction())
397397
expect(listener1.calls.length).toBe(1)
398-
expect(listener2.calls.length).toBe(3)
399-
expect(listener3.calls.length).toBe(3)
398+
expect(listener2.calls.length).toBe(2)
399+
expect(listener3.calls.length).toBe(2)
400400
expect(listener4.calls.length).toBe(1)
401401
})
402402

403+
it('notifies a listener unsubscribed with nested dispatch with the new state', () => {
404+
const store = createStore(reducers.todos)
405+
406+
var firstCall = true
407+
const listener1 = expect.createSpy().andCall(() => {
408+
unsubscribe2()
409+
if (firstCall) {
410+
firstCall = false
411+
store.dispatch(unknownAction())
412+
}
413+
})
414+
const listener2 = expect.createSpy()
415+
416+
store.subscribe(listener1)
417+
let unsubscribe2 = store.subscribe(listener2)
418+
419+
store.dispatch(unknownAction())
420+
expect(listener1.calls.length).toBe(2)
421+
expect(listener2.calls.length).toBe(1)
422+
})
423+
424+
403425
it('provides an up-to-date state when a subscriber is notified', done => {
404426
const store = createStore(reducers.todos)
405427
store.subscribe(() => {

0 commit comments

Comments
 (0)