Skip to content

Commit 6ebbe64

Browse files
jmplahitkoJoe Plahitko
and
Joe Plahitko
authored
feat: Allow action subscribers to catch rejections. (#1740)
close #1489 #1558 #1625 Co-authored-by: Joe Plahitko <[email protected]>
1 parent dfacba6 commit 6ebbe64

File tree

4 files changed

+123
-11
lines changed

4 files changed

+123
-11
lines changed

src/store.js

+25-11
Original file line numberDiff line numberDiff line change
@@ -149,18 +149,32 @@ export class Store {
149149
? Promise.all(entry.map(handler => handler(payload)))
150150
: entry[0](payload)
151151

152-
return result.then(res => {
153-
try {
154-
this._actionSubscribers
155-
.filter(sub => sub.after)
156-
.forEach(sub => sub.after(action, this.state))
157-
} catch (e) {
158-
if (__DEV__) {
159-
console.warn(`[vuex] error in after action subscribers: `)
160-
console.error(e)
152+
return new Promise((resolve, reject) => {
153+
result.then(res => {
154+
try {
155+
this._actionSubscribers
156+
.filter(sub => sub.after)
157+
.forEach(sub => sub.after(action, this.state))
158+
} catch (e) {
159+
if (__DEV__) {
160+
console.warn(`[vuex] error in after action subscribers: `)
161+
console.error(e)
162+
}
161163
}
162-
}
163-
return res
164+
resolve(res)
165+
}, e => {
166+
try {
167+
this._actionSubscribers
168+
.filter(sub => sub.error)
169+
.forEach(sub => sub.error(action, this.state, e))
170+
} catch (_e) {
171+
if (__DEV__) {
172+
console.warn(`[vuex] error in error action subscribers: `)
173+
console.error(_e)
174+
}
175+
}
176+
reject(e)
177+
})
164178
})
165179
}
166180

test/unit/modules.spec.js

+40
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,46 @@ describe('Modules', () => {
733733
})
734734
})
735735

736+
it('action error subscribers', (done) => {
737+
const beforeSpy = jasmine.createSpy()
738+
const afterSpy = jasmine.createSpy()
739+
const errorSpy = jasmine.createSpy()
740+
const error = new Error()
741+
const store = new Vuex.Store({
742+
actions: {
743+
[TEST]: () => Promise.reject(error)
744+
},
745+
plugins: [
746+
store => {
747+
store.subscribeAction({
748+
before: beforeSpy,
749+
after: afterSpy,
750+
error: errorSpy
751+
})
752+
}
753+
]
754+
})
755+
store.dispatch(TEST, 2).catch(() => {
756+
expect(beforeSpy).toHaveBeenCalledWith(
757+
{ type: TEST, payload: 2 },
758+
store.state
759+
)
760+
expect(afterSpy).not.toHaveBeenCalled()
761+
Vue.nextTick(() => {
762+
expect(afterSpy).not.toHaveBeenCalledWith(
763+
{ type: TEST, payload: 2 },
764+
store.state
765+
)
766+
expect(errorSpy).toHaveBeenCalledWith(
767+
{ type: TEST, payload: 2 },
768+
store.state,
769+
error
770+
)
771+
done()
772+
})
773+
})
774+
})
775+
736776
it('asserts a mutation should be a function', () => {
737777
expect(() => {
738778
new Vuex.Store({

types/index.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,12 @@ export interface SubscribeOptions {
7777
}
7878

7979
export type ActionSubscriber<P, S> = (action: P, state: S) => any;
80+
export type ActionErrorSubscriber<P, S> = (action: P, state: S, error: Error) => any;
8081

8182
export interface ActionSubscribersObject<P, S> {
8283
before?: ActionSubscriber<P, S>;
8384
after?: ActionSubscriber<P, S>;
85+
error?: ActionErrorSubscriber<P, S>;
8486
}
8587

8688
export type SubscribeActionOptions<P, S> = ActionSubscriber<P, S> | ActionSubscribersObject<P, S>;

types/test/index.ts

+56
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,67 @@ namespace StoreInstance {
6868
}
6969
});
7070

71+
store.subscribeAction({
72+
before(action, state) {
73+
action.type;
74+
action.payload;
75+
state.value;
76+
},
77+
error(action, state, error) {
78+
action.type;
79+
action.payload;
80+
state.value;
81+
error;
82+
}
83+
});
84+
85+
store.subscribeAction({
86+
before(action, state) {
87+
action.type;
88+
action.payload;
89+
state.value;
90+
},
91+
after(action, state) {
92+
action.type;
93+
action.payload;
94+
state.value;
95+
},
96+
error(action, state, error) {
97+
action.type;
98+
action.payload;
99+
state.value;
100+
error;
101+
}
102+
});
103+
104+
store.subscribeAction({
105+
after(action, state) {
106+
action.type;
107+
action.payload;
108+
state.value;
109+
}
110+
});
111+
71112
store.subscribeAction({
72113
after(action, state) {
73114
action.type;
74115
action.payload;
75116
state.value;
117+
},
118+
error(action, state, error) {
119+
action.type;
120+
action.payload;
121+
state.value;
122+
error;
123+
}
124+
});
125+
126+
store.subscribeAction({
127+
error(action, state, error) {
128+
action.type;
129+
action.payload;
130+
state.value;
131+
error;
76132
}
77133
});
78134

0 commit comments

Comments
 (0)