Skip to content

Commit 1195fea

Browse files
committed
Merge pull request jakesgordon#10 from cboone/feature/custom_error_callback
- Added custom event error callbacks
2 parents bbe62d9 + 879bcbb commit 1195fea

4 files changed

Lines changed: 60 additions & 5 deletions

File tree

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,24 @@ same as the first example in this section where you simply define your own start
282282

283283
So you have a number of choices available to you when initializing your state machine.
284284

285+
Handling Failures
286+
======================
287+
288+
By default, if you try to call an event method that is not allowed in the current state, the
289+
state machine will throw an exception. If you prefer to handle the problem yourself, you can
290+
define a custom `error` handler, which takes a single event name parameter:
291+
292+
var fsm = StateMachine.create({
293+
initial: 'green',
294+
error: function(eventName) {
295+
return 'event ' + eventName + ' not allowed in current state ' + this.current;
296+
},
297+
events: [
298+
{ name: 'panic', from: 'green', to: 'red' },
299+
{ name: 'calm', from: 'red', to: 'green' },
300+
]});
301+
alert(fsm.calm()); // "event calm not allowed in current state green"
302+
285303
Release Notes
286304
=============
287305

state-machine.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ StateMachine = {
3131

3232
for(var name in map) {
3333
if (map.hasOwnProperty(name))
34-
fsm[name] = StateMachine.buildEvent(name, map[name]);
34+
fsm[name] = StateMachine.buildEvent(name, map[name], cfg.error);
3535
}
3636

3737
for(var name in callbacks) {
@@ -83,14 +83,19 @@ StateMachine = {
8383
return func.apply(this, [name, from, to].concat(args));
8484
},
8585

86-
buildEvent: function(name, map) {
86+
buildEvent: function(name, map, errorHandler) {
8787
return function() {
8888

8989
if (this.transition)
9090
throw "event " + name + " inappropriate because previous transition did not complete"
9191

92-
if (this.cannot(name))
93-
throw "event " + name + " inappropriate in current state " + this.current;
92+
if (this.cannot(name)) {
93+
if (errorHandler) {
94+
return errorHandler.call(this, name);
95+
} else {
96+
throw "event " + name + " inappropriate in current state " + this.current;
97+
}
98+
}
9499

95100
var from = this.current;
96101
var to = map[from];

state-machine.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/test_basics.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,38 @@ test("inappropriate events", function() {
148148

149149
//-----------------------------------------------------------------------------
150150

151+
test("inappropriate event handling can be customized", function() {
152+
153+
var fsm = StateMachine.create({
154+
error: function(eventName) {
155+
return 'event ' + eventName + ' inappropriate in current state ' + this.current;
156+
},
157+
initial: 'green',
158+
events: [
159+
{ name: 'warn', from: 'green', to: 'yellow' },
160+
{ name: 'panic', from: 'yellow', to: 'red' },
161+
{ name: 'calm', from: 'red', to: 'yellow' }
162+
]});
163+
164+
equals(fsm.current, 'green', "initial state should be green");
165+
166+
equals(fsm.panic(), 'event panic inappropriate in current state green');
167+
equals(fsm.calm(), 'event calm inappropriate in current state green');
168+
169+
fsm.warn();
170+
equals(fsm.current, 'yellow', "current state should be yellow");
171+
equals(fsm.warn(), 'event warn inappropriate in current state yellow');
172+
equals(fsm.calm(), 'event calm inappropriate in current state yellow');
173+
174+
fsm.panic();
175+
equals(fsm.current, 'red', "current state should be red");
176+
equals(fsm.warn(), 'event warn inappropriate in current state red');
177+
equals(fsm.panic(), 'event panic inappropriate in current state red');
178+
179+
});
180+
181+
//-----------------------------------------------------------------------------
182+
151183
test("event is cancelable", function() {
152184

153185
var fsm = StateMachine.create({

0 commit comments

Comments
 (0)