Skip to content

Commit c28f8c3

Browse files
committed
feat: subscribeAction
Allows to listen dispatched actions
1 parent 7d9730e commit c28f8c3

File tree

3 files changed

+61
-11
lines changed

3 files changed

+61
-11
lines changed

src/store.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export class Store {
3535
// store internal state
3636
this._committing = false
3737
this._actions = Object.create(null)
38+
this._actionSubscribers = []
3839
this._mutations = Object.create(null)
3940
this._wrappedGetters = Object.create(null)
4041
this._modules = new ModuleCollection(options)
@@ -123,29 +124,28 @@ export class Store {
123124
payload
124125
} = unifyObjectStyle(_type, _payload)
125126

127+
const action = { type, payload }
126128
const entry = this._actions[type]
127129
if (!entry) {
128130
if (process.env.NODE_ENV !== 'production') {
129131
console.error(`[vuex] unknown action type: ${type}`)
130132
}
131133
return
132134
}
135+
136+
this._actionSubscribers.forEach(sub => sub(action, this.state))
137+
133138
return entry.length > 1
134139
? Promise.all(entry.map(handler => handler(payload)))
135140
: entry[0](payload)
136141
}
137142

138143
subscribe (fn) {
139-
const subs = this._subscribers
140-
if (subs.indexOf(fn) < 0) {
141-
subs.push(fn)
142-
}
143-
return () => {
144-
const i = subs.indexOf(fn)
145-
if (i > -1) {
146-
subs.splice(i, 1)
147-
}
148-
}
144+
return genericSubscribe(fn, this._subscribers)
145+
}
146+
147+
subscribeAction (fn) {
148+
return genericSubscribe(fn, this._actionSubscribers)
149149
}
150150

151151
watch (getter, cb, options) {
@@ -203,6 +203,18 @@ export class Store {
203203
}
204204
}
205205

206+
function genericSubscribe (fn, subs) {
207+
if (subs.indexOf(fn) < 0) {
208+
subs.push(fn)
209+
}
210+
return () => {
211+
const i = subs.indexOf(fn)
212+
if (i > -1) {
213+
subs.splice(i, 1)
214+
}
215+
}
216+
}
217+
206218
function resetStore (store, hot) {
207219
store._actions = Object.create(null)
208220
store._mutations = Object.create(null)

test/unit/modules.spec.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,9 @@ describe('Modules', () => {
553553

554554
it('plugins', function () {
555555
let initState
556+
const actionSpy = jasmine.createSpy()
556557
const mutations = []
558+
const subscribeActionSpy = jasmine.createSpy()
557559
const store = new Vuex.Store({
558560
state: {
559561
a: 1
@@ -563,21 +565,31 @@ describe('Modules', () => {
563565
state.a += n
564566
}
565567
},
568+
actions: {
569+
[TEST]: actionSpy
570+
},
566571
plugins: [
567572
store => {
568573
initState = store.state
569574
store.subscribe((mut, state) => {
570-
expect(state).toBe(store.state)
575+
expect(state).toBe(state)
571576
mutations.push(mut)
572577
})
578+
store.subscribeAction(subscribeActionSpy)
573579
}
574580
]
575581
})
576582
expect(initState).toBe(store.state)
577583
store.commit(TEST, 2)
584+
store.dispatch(TEST, 2)
578585
expect(mutations.length).toBe(1)
579586
expect(mutations[0].type).toBe(TEST)
580587
expect(mutations[0].payload).toBe(2)
588+
expect(actionSpy).toHaveBeenCalled()
589+
expect(subscribeActionSpy).toHaveBeenCalledWith(
590+
{ type: TEST, payload: 2 },
591+
store.state
592+
)
581593
})
582594
})
583595

test/unit/store.spec.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,32 @@ describe('Store', () => {
286286
expect(store.state.a).toBe(3)
287287
})
288288

289+
it('subscribe: should handle subscriptions / unsubscriptions', () => {
290+
const subscribeSpy = jasmine.createSpy()
291+
const secondSubscribeSpy = jasmine.createSpy()
292+
const testPayload = 2
293+
const store = new Vuex.Store({
294+
state: {},
295+
mutations: {
296+
[TEST]: () => {}
297+
}
298+
})
299+
300+
const unsubscribe = store.subscribe(subscribeSpy)
301+
store.subscribe(secondSubscribeSpy)
302+
store.commit(TEST, testPayload)
303+
unsubscribe()
304+
store.commit(TEST, testPayload)
305+
306+
expect(subscribeSpy).toHaveBeenCalledWith(
307+
{ type: TEST, payload: testPayload },
308+
store.state
309+
)
310+
expect(secondSubscribeSpy).toHaveBeenCalled()
311+
expect(subscribeSpy.calls.count()).toBe(1)
312+
expect(secondSubscribeSpy.calls.count()).toBe(2)
313+
})
314+
289315
// store.watch should only be asserted in non-SSR environment
290316
if (!isSSR) {
291317
it('strict mode: warn mutations outside of handlers', () => {

0 commit comments

Comments
 (0)