Skip to content

Commit a7e63a5

Browse files
committed
Add nice overview
1 parent b74067b commit a7e63a5

File tree

1 file changed

+153
-1
lines changed

1 file changed

+153
-1
lines changed

readme.md

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,78 @@
3131
npm add yieldmachine
3232
```
3333

34-
## `start(machineDefinition: GeneratorFunction)`
34+
## Overview
35+
36+
You define your machine using a function. For example, you could define a state machine representing a light switch. We’ll name our function `Switch`.
37+
38+
```ts
39+
function Switch() {
40+
41+
}
42+
```
43+
44+
Inside you declare each state you want as a [generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*).
45+
46+
Our `Switch` will have two states: `Off` and `On`. We return `Off` as that’s what we want as our initial state to be — our light is off by default.
47+
48+
```ts
49+
import { on, start } from "yieldmachine";
50+
51+
function Switch() {
52+
function* Off() {
53+
}
54+
function* On() {
55+
}
56+
57+
return Off;
58+
}
59+
```
60+
61+
Our `Switch` can be flicked on and off. The string `"FLICK"` is our event that will represent the flicking on and off of our switch.
62+
63+
When our `Switch` is `Off` and it is sent a `FLICK` event, it transitions to `On`.
64+
65+
And, when our `Switch` is `On` and it is sent a `FLICK` event, it transitions back to `Off`.
66+
67+
```ts
68+
import { on, start } from "yieldmachine";
69+
70+
function Switch() {
71+
function* Off() {
72+
yield on("FLICK", On);
73+
}
74+
function* On() {
75+
yield on("FLICK", Off);
76+
}
77+
78+
return Off;
79+
}
80+
```
81+
82+
Now our machine is ready to be run. We pass our `Switch` to the `start` function we import from `yieldmachine`, and it will run an instance of our machine. And as we send it `"FLICK"` message, you’ll see the `current` state of our machine instance change.
83+
84+
```ts
85+
const machine = start(Switch);
86+
machine.current; // "Off"
87+
machine.next("FLICK");
88+
machine.current; // "On"
89+
machine.next("TOGGLE");
90+
machine.current; // "Off"
91+
```
92+
93+
## Benefits of Generator Functions
94+
95+
- Generator Functions are a built-in feature of JavaScript and TypeScript.
96+
- They have built-in syntax highlighting, autocompletion, and general rich language support in editors like Visual Studio Code.
97+
- Our states are represented by actual JavaScript functions.
98+
- This means if we pass a state that’s either spelled incorrectly or isn’t in scope, our editor will tell us.
99+
- Our states use the name of the function.
100+
- Generator Functions can be reused, composed, and partially applied like any function. This increases the modularity and reuse of our machine parts.
101+
- Coming soon: our machine definitions can be serialized and deserialized. This means they could be generated on a back-end and sent to the front-end. They could be stored away in a database. They could even be generated dynamically on the fly.
102+
103+
## Documentation
104+
105+
### `start(machineDefinition: Function | GeneratorFunction)`
35106

36107
Starts a machine, transitioning to its initially returned state.
37108

@@ -62,14 +133,95 @@ Cleans up the machine.
62133

63134
Transitions to the target state when the given event occurs.
64135

136+
```ts
137+
import { on, start } from "yieldmachine";
138+
139+
function Switch() {
140+
function* Off() {
141+
yield on("FLICK", On);
142+
yield on("TOGGLE", On);
143+
}
144+
function* On() {
145+
yield on("FLICK", Off);
146+
yield on("TOGGLE", Off);
147+
}
148+
149+
return Off;
150+
}
151+
152+
const machine = start(Switch);
153+
machine.current; // "Off"
154+
machine.next("FLICK");
155+
machine.current; // "On"
156+
machine.next("TOGGLE");
157+
machine.current; // "Off"
158+
```
159+
65160
### `enter(action: () => undefined | unknown | Promise<unknown>)`
66161

67162
Runs the provided function when this state is entered. If the function returns a promise, its value is made available in the `.results` property of the machine, keyed by the name of this passed function.
68163

164+
```ts
165+
import { start, on, enter } from "yieldmachine";
166+
167+
let onCount = 0;
168+
function recordOn() {
169+
onCount++;
170+
}
171+
172+
function Switch() {
173+
function* Off() {
174+
yield on("FLICK", On);
175+
}
176+
function* On() {
177+
yield enter(recordOn);
178+
yield on("FLICK", Off);
179+
}
180+
181+
return Off;
182+
}
183+
184+
const machine = start(Switch);
185+
machine.next("FLICK");
186+
console.log(recordOn, machine.current); // 1, "ON"
187+
machine.next("FLICK");
188+
console.log(recordOn, machine.current); // 1, "OFF"
189+
machine.next("FLICK");
190+
console.log(recordOn, machine.current); // 2, "ON"
191+
```
192+
69193
### `exit(action: () => undefined | unknown | Promise<unknown>)`
70194

71195
Runs the provided function when this state is exited.
72196

197+
```ts
198+
import { start, on, exit } from "yieldmachine";
199+
200+
let lastSessionEnded = null;
201+
function recordSessionEnd() {
202+
lastSessionEnded = new Date();
203+
}
204+
205+
function Session() {
206+
function* SignedOut() {
207+
yield on("AUTHENTICATE", SignedIn);
208+
}
209+
function* SignedIn() {
210+
yield exit(recordSessionEnd);
211+
yield on("LOG_OFF", SignedOut);
212+
}
213+
214+
return SignedOut;
215+
}
216+
217+
const machine = start(Switch);
218+
console.log(lastSessionEnded, machine.current); // null, "SignedOut"
219+
machine.next("AUTHENTICATE");
220+
console.log(lastSessionEnded, machine.current); // null, "SignedIn"
221+
machine.next("LOG_OFF");
222+
console.log(lastSessionEnded, machine.current); // (current time), "SignedOut"
223+
```
224+
73225
### `cond(predicate: () => boolean, target: GeneratorFunction)`
74226

75227
Immediately transitions to the target state if the provided predicate function returns `true`.

0 commit comments

Comments
 (0)