Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guard action #16

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,33 @@ console.log(machine.state)
// }
```

## Guard

Sometimes you may want a machine to be guarded against moving to a specific state based on some condition. You can encapsulate this logic as part of your machine. For example, say we have a door and a lock:

```js
const door = nanostate("closed", {
closed: { open: "open", light_push: "ajar" },
ajar: { close: "closed", open: "open" },
open: { close: "closed" },
});
const lock = nanostate("unlocked", {
unlocked: { lock: "locked" },
locked: { unlock: "unlocked" },
});
```

If the door is closed, the door cannot be opened unless it is unlocked. Likewise, the door cannot be lightly pushed unless it is also unlocked.

```js
door.guard("open", () => {
return lockState.state === "unlocked";
});
door.guard("light_push", () => {
return lockState.state === "unlocked";
});
```

## Nanocomponent
Usage in combination with
[nanocomponent](https://github.com/choojs/nanocomponent) to create stateful UI
Expand Down Expand Up @@ -198,6 +225,10 @@ passed.
Trigger a callback when a certain state is entered. Useful to trigger side
effects upon state change.

### `machine.onchange(cb)`
Trigger a callback when any state is entered. Useful to trigger side
effects upon state change.

### `state = machine.state`
Return the current state.

Expand Down
16 changes: 16 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ function Nanostate (initialState, transitions) {
this.state = initialState
this.submachines = {}
this._submachine = null
this.guards = {}
this.onchangecb = null;

Nanobus.call(this)
}
Expand All @@ -21,6 +23,14 @@ Nanostate.prototype = Object.create(Nanobus.prototype)

Nanostate.prototype.constructor = Nanostate

Nanostate.prototype.onchange = function(cb) {
this.onchangecb = cb;
}

Nanostate.prototype.guard = function (eventName, cb) {
this.guards[eventName] = cb
}

Nanostate.prototype.emit = function (eventName) {
var nextState = this._next(eventName)
assert.ok(nextState, 'nanostate.emit: invalid transition' + this.state + '->' + eventName)
Expand All @@ -29,7 +39,13 @@ Nanostate.prototype.emit = function (eventName) {
this._unregister()
}

if (this.guards[eventName] && (this.guards[eventName]() === false)) {
return
}
this.state = nextState
if (this.onchangecb !== null && typeof this.onchangecb === 'function') {
this.onchangecb(nextState);
}
Nanobus.prototype.emit.call(this, nextState)
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "nanostate",
"description": "Small Finite State Machine implementation",
"repository": "choojs/nanostate",
"version": "1.2.2",
"version": "1.2.3",
"scripts": {
"start": "node .",
"lint": "standard",
Expand Down
16 changes: 16 additions & 0 deletions test/event.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
var tape = require("tape");

var nanostate = require("../");

tape("event - any change", (test) => {
test.plan(1);
var machine = nanostate("green", {
green: { timer: "yellow" },
yellow: { timer: "red" },
red: { timer: "green" },
});
machine.onchange((nextState) => {
test.equal(nextState, "yellow");
});
machine.emit("timer");
});
7 changes: 4 additions & 3 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require('./nanostate')
require('./parallel')
require('./hierarchical')
require("./nanostate");
require("./parallel");
require("./hierarchical");
require("./event");