From d4951fd641af32139c89ee85b3ce35fb67606efc Mon Sep 17 00:00:00 2001 From: cha0s Date: Wed, 20 Mar 2019 18:33:13 -0500 Subject: [PATCH] refactor: synchronizer in its own file --- packages/state/index.js | 72 +-------------------------- packages/state/synchronizer.js | 90 ++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 71 deletions(-) create mode 100644 packages/state/synchronizer.js diff --git a/packages/state/index.js b/packages/state/index.js index 1620837..071dbbd 100644 --- a/packages/state/index.js +++ b/packages/state/index.js @@ -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'; diff --git a/packages/state/synchronizer.js b/packages/state/synchronizer.js new file mode 100644 index 0000000..17c4746 --- /dev/null +++ b/packages/state/synchronizer.js @@ -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 = {};