fluidstate
Advanced tools
Comparing version 0.0.4 to 0.0.5
@@ -89,8 +89,12 @@ "use strict"; | ||
const createEffect = (calculate, perform) => { | ||
const effectId = {}; | ||
const computed = createComputed(() => { | ||
const computedValue = calculate(); | ||
updateManager.callWithoutCollect(() => perform(computedValue)); | ||
updateManager.addEffect(effectId, () => perform(computedValue)); | ||
return computedValue; | ||
}); | ||
return () => dependenciesManager.disableComputed(computed); | ||
return () => { | ||
dependenciesManager.disableComputed(computed); | ||
updateManager.cancelEffect(effectId); | ||
}; | ||
}; | ||
@@ -97,0 +101,0 @@ return { |
{ | ||
"name": "fluidstate", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "Library for fine-grained reactivity state management", | ||
@@ -5,0 +5,0 @@ "repository": "https://gitlab.com/fluidstate/fluidstate", |
@@ -9,4 +9,5 @@ import { DependenciesManager } from "./dependencies-manager"; | ||
get: <T_2>(node: Node<T_2>) => T_2; | ||
callWithoutCollect: <T_3>(fn: () => T_3) => T_3; | ||
batch: (update: () => void) => void; | ||
addEffect: (effectId: object, perform: () => void) => void; | ||
cancelEffect: (effectId: object) => void; | ||
}; |
@@ -9,53 +9,7 @@ "use strict"; | ||
var _singleUpdateManager = require("./single-update-manager"); | ||
const createUpdateManager = (configuration, dependenciesManager, nodeCollector) => { | ||
let scheduledId = null; | ||
const createNodeUpdateManager = (cancelScheduledUpdate, performEffects, dependenciesManager) => { | ||
let scheduledUpdates = []; | ||
let currentUpdateIndex = -1; | ||
const set = (node, newValue) => { | ||
if (!node.inert.equal(newValue)) { | ||
node.inert.set(newValue); | ||
scheduleUpdate(node); | ||
} | ||
}; | ||
/** | ||
* Schedule update without changing values | ||
*/ | ||
const notify = node => { | ||
scheduleUpdate(node); | ||
}; | ||
let collectionPauseCount = 0; | ||
const callWithoutCollect = fn => { | ||
collectionPauseCount++; | ||
try { | ||
return fn(); | ||
} finally { | ||
collectionPauseCount--; | ||
} | ||
}; | ||
const get = node => { | ||
// If we call .get() during the current update, | ||
// we shouldn't retrigger the update. If we call .get() | ||
// outside of the existing update, we need to trigger | ||
// the update, since a dependency might have changed. | ||
if (currentUpdateIndex < 0 && batchingCount === 0) { | ||
triggerUpdate(); | ||
} | ||
if (collectionPauseCount === 0) { | ||
nodeCollector.collect(node); | ||
} | ||
return node.inert.get(); | ||
}; | ||
let batchingCount = 0; | ||
const batch = update => { | ||
batchingCount++; | ||
try { | ||
update(); | ||
} finally { | ||
batchingCount--; | ||
if (batchingCount === 0 && scheduledUpdates.length > 0) { | ||
scheduleNextUpdate(); | ||
} | ||
} | ||
}; | ||
const isNodeAddedToSchedule = () => scheduledUpdates.length > 0; | ||
const isUpdateInProgress = () => currentUpdateIndex >= 0; | ||
const addNodeToSchedule = node => { | ||
@@ -76,18 +30,2 @@ // We should either add to the next update (if the current update | ||
}; | ||
const scheduleNextUpdate = () => { | ||
// If the update is already scheduled, we should just | ||
// wait for it rather than scheduling it again | ||
if (scheduledId === null) { | ||
scheduledId = configuration.scheduleFunction(() => { | ||
scheduledId = null; | ||
triggerUpdate(); | ||
}); | ||
} | ||
}; | ||
const scheduleUpdate = node => { | ||
addNodeToSchedule(node); | ||
if (batchingCount === 0) { | ||
scheduleNextUpdate(); | ||
} | ||
}; | ||
const triggerUpdate = () => { | ||
@@ -97,6 +35,4 @@ // If we call triggerUpdate() after the update was | ||
// just run it synchronously | ||
if (scheduledId !== null) { | ||
configuration.cancelFunction(scheduledId); | ||
scheduledId = null; | ||
} | ||
cancelScheduledUpdate(); | ||
// If there's no scheduledUpdates, e.g. during outside ".get()" call, | ||
@@ -106,2 +42,3 @@ // when nothing was ".set" before ".get" is called, | ||
if (scheduledUpdates.length === 0) { | ||
performEffects(); | ||
return; | ||
@@ -117,2 +54,3 @@ } | ||
cleanupUpdate(); | ||
performEffects(); | ||
} | ||
@@ -125,7 +63,144 @@ }; | ||
return { | ||
isNodeAddedToSchedule, | ||
isUpdateInProgress, | ||
addNodeToSchedule, | ||
triggerUpdate | ||
}; | ||
}; | ||
const createScheduleManager = (configuration, triggerUpdate) => { | ||
let scheduledId = null; | ||
const scheduleNextUpdate = () => { | ||
// If the update is already scheduled, we should just | ||
// wait for it rather than scheduling it again | ||
if (scheduledId === null) { | ||
scheduledId = configuration.scheduleFunction(() => { | ||
scheduledId = null; | ||
triggerUpdate(); | ||
}); | ||
} | ||
}; | ||
const cancelScheduledUpdate = () => { | ||
if (scheduledId !== null) { | ||
configuration.cancelFunction(scheduledId); | ||
scheduledId = null; | ||
} | ||
}; | ||
return { | ||
scheduleNextUpdate, | ||
cancelScheduledUpdate | ||
}; | ||
}; | ||
const createBatchManager = (isNodeAddedToSchedule, scheduleNextUpdate) => { | ||
const isCurrentlyBatching = () => batchingCount > 0; | ||
let batchingCount = 0; | ||
const batch = update => { | ||
batchingCount++; | ||
try { | ||
update(); | ||
} finally { | ||
batchingCount--; | ||
if (!isCurrentlyBatching() && isNodeAddedToSchedule()) { | ||
scheduleNextUpdate(); | ||
} | ||
} | ||
}; | ||
return { | ||
isCurrentlyBatching, | ||
batch | ||
}; | ||
}; | ||
const createEffectsManager = isUpdateInProgress => { | ||
let scheduledEffects = []; | ||
const performEffects = () => { | ||
let effects = scheduledEffects; | ||
scheduledEffects = []; | ||
for (let i = 0; i < effects.length; i++) { | ||
const { | ||
perform | ||
} = effects[i]; | ||
perform(); | ||
} | ||
}; | ||
const addEffect = (effectId, perform) => { | ||
if (!isUpdateInProgress()) { | ||
perform(); | ||
} else { | ||
cancelEffect(effectId); | ||
scheduledEffects.push({ | ||
effectId, | ||
perform | ||
}); | ||
} | ||
}; | ||
const cancelEffect = effectId => { | ||
for (let i = 0; i < scheduledEffects.length; i++) { | ||
if (scheduledEffects[i].effectId === effectId) { | ||
scheduledEffects.splice(i, 1); | ||
break; | ||
} | ||
} | ||
}; | ||
return { | ||
performEffects, | ||
addEffect, | ||
cancelEffect | ||
}; | ||
}; | ||
const createUpdateManager = (configuration, dependenciesManager, nodeCollector) => { | ||
const set = (node, newValue) => { | ||
if (!node.inert.equal(newValue)) { | ||
node.inert.set(newValue); | ||
scheduleUpdate(node); | ||
} | ||
}; | ||
/** | ||
* Schedule update without changing values | ||
*/ | ||
const notify = node => { | ||
scheduleUpdate(node); | ||
}; | ||
const get = node => { | ||
// If we call .get() during the current update, | ||
// we shouldn't retrigger the update. If we call .get() | ||
// outside of the existing update, we need to trigger | ||
// the update, since a dependency might have changed. | ||
if (!isUpdateInProgress() && !isCurrentlyBatching()) { | ||
triggerUpdate(); | ||
} | ||
nodeCollector.collect(node); | ||
return node.inert.get(); | ||
}; | ||
const { | ||
cancelScheduledUpdate, | ||
scheduleNextUpdate | ||
} = createScheduleManager(configuration, () => triggerUpdate()); | ||
const { | ||
isCurrentlyBatching, | ||
batch | ||
} = createBatchManager(() => isNodeAddedToSchedule(), scheduleNextUpdate); | ||
const scheduleUpdate = node => { | ||
addNodeToSchedule(node); | ||
if (!isCurrentlyBatching()) { | ||
scheduleNextUpdate(); | ||
} | ||
}; | ||
const { | ||
addEffect, | ||
cancelEffect, | ||
performEffects | ||
} = createEffectsManager(() => isUpdateInProgress()); | ||
const { | ||
addNodeToSchedule, | ||
isUpdateInProgress, | ||
isNodeAddedToSchedule, | ||
triggerUpdate | ||
} = createNodeUpdateManager(cancelScheduledUpdate, performEffects, dependenciesManager); | ||
return { | ||
set, | ||
notify, | ||
get, | ||
callWithoutCollect, | ||
batch | ||
batch, | ||
addEffect, | ||
cancelEffect | ||
}; | ||
@@ -132,0 +207,0 @@ }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
197724
1952