Skip to content

Commit 907c94c

Browse files
committed
Merge pull request #296 from goatslacker/278
Adding a batching function for the dispatcher
2 parents 4cf98e3 + cd48286 commit 907c94c

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed

src/alt/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Alt {
1414
this.serialize = config.serialize || JSON.stringify
1515
this.deserialize = config.deserialize || JSON.parse
1616
this.dispatcher = config.dispatcher || new Dispatcher()
17+
this.batchingFunction = config.batchingFunction || (callback => callback())
1718
this.actions = { global: {} }
1819
this.stores = {}
1920
this.storeTransforms = config.storeTransforms || []
@@ -23,7 +24,7 @@ class Alt {
2324
}
2425

2526
dispatch(action, data, details) {
26-
this.dispatcher.dispatch({ action, data, details })
27+
this.batchingFunction(() => this.dispatcher.dispatch({ action, data, details }))
2728
}
2829

2930
createUnsavedStore(StoreModel, ...args) {

test/batching-test.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { jsdom } from 'jsdom'
2+
import Alt from '../'
3+
import React from 'react/addons'
4+
import { assert } from 'chai'
5+
import sinon from 'sinon'
6+
7+
const { TestUtils } = React.addons
8+
9+
const Actions = {
10+
buttonClick() {
11+
setTimeout(() => {
12+
this.actions.switchComponent()
13+
}, 10)
14+
},
15+
16+
switchComponent() {
17+
this.dispatch()
18+
},
19+
20+
uhoh() {
21+
this.dispatch()
22+
}
23+
}
24+
25+
function Store(actions) {
26+
this.active = false
27+
28+
this.bindAction(actions.switchComponent, () => {
29+
this.active = true
30+
})
31+
}
32+
33+
class ComponentA extends React.Component {
34+
constructor(props) {
35+
super(props)
36+
37+
this.state = props.alt.stores.store.getState()
38+
}
39+
40+
componentWillMount() {
41+
this.props.alt.stores.store.listen(state => this.setState(state))
42+
}
43+
44+
render() {
45+
if (this.state.active) {
46+
return <ComponentB alt={this.props.alt} callback={this.props.callback} />
47+
} else {
48+
return <div />
49+
}
50+
}
51+
}
52+
53+
class ComponentB extends React.Component {
54+
componentWillMount() {
55+
let error = null
56+
try {
57+
this.props.alt.actions.actions.uhoh()
58+
} catch (err) {
59+
error = err
60+
} finally {
61+
this.props.callback(error)
62+
}
63+
}
64+
65+
render() {
66+
return <div />
67+
}
68+
}
69+
70+
export default {
71+
'Batching dispatcher': {
72+
beforeEach() {
73+
global.document = jsdom('<!doctype html><html><body></body></html>')
74+
global.window = global.document.parentWindow
75+
global.navigator = global.window.navigator
76+
},
77+
78+
afterEach() {
79+
delete global.document
80+
delete global.window
81+
delete global.navigator
82+
},
83+
84+
'does not batch'(done) {
85+
const alt = new Alt()
86+
alt.addActions('actions', Actions)
87+
alt.addStore('store', Store, alt.actions.actions)
88+
89+
function test(err) {
90+
assert.match(err, /dispatch in the middle of a dispatch/)
91+
done()
92+
}
93+
94+
TestUtils.renderIntoDocument(<ComponentA alt={alt} callback={test} />)
95+
alt.actions.actions.buttonClick()
96+
},
97+
98+
'allows batching'(done) {
99+
const alt = new Alt({ batchingFunction: React.addons.batchedUpdates })
100+
alt.addActions('actions', Actions)
101+
alt.addStore('store', Store, alt.actions.actions)
102+
103+
function test(err) {
104+
assert.isNull(err)
105+
done()
106+
}
107+
108+
TestUtils.renderIntoDocument(<ComponentA alt={alt} callback={test} />)
109+
alt.actions.actions.buttonClick()
110+
},
111+
}
112+
}

0 commit comments

Comments
 (0)