refactor: synchronizer in its own file

This commit is contained in:
cha0s 2019-03-20 18:33:13 -05:00
parent 8f7e8bb5f0
commit d4951fd641
2 changed files with 91 additions and 71 deletions

View File

@ -1,71 +1 @@
import * as I from 'immutable';
import immutablediff from 'immutablediff';
export class StateSynchronizer {
constructor(statefuls) {
this._state = I.Map();
this._statefuls = statefuls;
this.updateState();
}
acceptStateChange(change) {
for (const key in change) {
const stateful = this._statefuls[key];
if (!stateful) {
continue;
}
stateful.acceptStateChange(change[key]);
}
}
diff() {
const state = this.state();
if (this.previousState === state) {
return StateSynchronizer.noChange;
}
// Take a pure JS diff.
const steps = immutablediff(this.previousState, state).toJS();
let diff = {};
for (const {op, path, value} of steps) {
if ('replace' === op || 'add' === op) {
if ('/' === path) {
diff = value;
}
else {
const parts = path.split('/');
parts.shift();
let walk = diff;
for (let i = 0; i < parts.length; ++i) {
const part = parts[i];
walk[part] = walk[part] || {};
if (i === parts.length - 1) {
walk[part] = value;
}
else {
walk = walk[part];
}
}
}
}
}
// Side-effect.
this.previousState = this.state();
return diff;
}
state() {
this.updateState();
return this._state;
}
updateState() {
for (const key in this._statefuls) {
const stateful = this._statefuls[key];
this._state = this._state.set(key, stateful.state());
}
}
}
StateSynchronizer.noChange = {};
export {StateSynchronizer} from './synchronizer';

View File

@ -0,0 +1,90 @@
import * as I from 'immutable';
import immutablediff from 'immutablediff';
export class StateSynchronizer {
constructor(statefuls) {
this._previousState = I.Map();
this._state = I.Map();
this._statefuls = statefuls;
this.updateState();
}
acceptStateChange(change) {
for (const key in change) {
const stateful = this._statefuls[key];
if (!stateful) {
continue;
}
stateful.acceptStateChange(change[key]);
}
}
diff() {
const state = this.state();
// if (this._previousState === state) {
// return StateSynchronizer.noChange;
// }
const diff = {};
let dirty = false;
for (const key in this._statefuls) {
if (this._previousState.get(key) !== state.get(key)) {
diff[key] = this.diffStateful(
this._previousState.get(key),
state.get(key)
);
dirty = true;
}
}
// Side-effect.
this._previousState = this.state();
if (!dirty) {
return StateSynchronizer.noChange;
}
return diff;
}
diffStateful(previous, current) {
// Take a pure JS diff.
const steps = immutablediff(previous, current).toJS();
let diff = {};
for (const {op, path, value} of steps) {
if ('replace' === op || 'add' === op) {
if ('/' === path) {
diff = value;
}
else {
const parts = path.split('/');
parts.shift();
let walk = diff;
for (let i = 0; i < parts.length; ++i) {
const part = parts[i];
walk[part] = walk[part] || {};
if (i === parts.length - 1) {
walk[part] = value;
}
else {
walk = walk[part];
}
}
}
}
}
return diff;
}
state() {
this.updateState();
return this._state;
}
updateState() {
for (const key in this._statefuls) {
const stateful = this._statefuls[key];
this._state = this._state.set(key, stateful.state());
}
}
}
StateSynchronizer.noChange = {};