Sukima12th February 2020 at 1:01pm
This is designed to be used with the Simple State Machine micro lib.
See also, CSS based view states.
(function() {
let activeService = null;
let batchedTransitions = new Map();
function nop() {}
function interpret(machine) {
let listeners = new Set();
let status = 'not-started';
let state = machine.initialState;
function capture(fn) {
return function (...args) {
activeService = service;
let ret = fn(...args);
activeService = null;
let fifo = batchedTransitions.get(service) || [];
let next = fifo.shift();
if (next) { service.send(next); }
return ret;
};
}
const service = {
subscribe: capture(function (listener) {
listeners.add(listener);
listener(state);
return { unsubscribe: () => listeners.delete(listener) };
}),
send: capture(function (event) {
state = machine.transition(state, event);
state.actions.forEach(({ exec = nop }) => exec(state.context, event));
listeners.forEach(listener => listener(state, event));
return service;
}),
start: capture(function () {
status = 'running';
state.actions.forEach(({ exec = nop }) => exec(state.context, '#init'));
return service;
}),
stop() {
status = 'stopped';
listeners.clear();
return service;
},
get status() { return status; },
};
return service;
};
interpret.send = function send(event) {
return function() {
let fifo = batchedTransitions.get(activeService) || [];
fifo.push(event);
batchedTransitions.set(activeService, fifo);
};
};
return interpret;
})();