fix(core): serialize state mutations, fix batch flushing/reentrancy, handle falsy initial values, dispose old StatePart on force, and improve notification/error handling
This commit is contained in:
@@ -14,6 +14,7 @@ export class Smartstate<StatePartNameType extends string> {
|
||||
|
||||
// Batch support
|
||||
private batchDepth = 0;
|
||||
private isFlushing = false;
|
||||
private pendingNotifications = new Set<StatePart<any, any>>();
|
||||
|
||||
constructor() {}
|
||||
@@ -41,11 +42,18 @@ export class Smartstate<StatePartNameType extends string> {
|
||||
await updateFn();
|
||||
} finally {
|
||||
this.batchDepth--;
|
||||
if (this.batchDepth === 0) {
|
||||
const pending = [...this.pendingNotifications];
|
||||
this.pendingNotifications.clear();
|
||||
for (const sp of pending) {
|
||||
await sp.notifyChange();
|
||||
if (this.batchDepth === 0 && !this.isFlushing) {
|
||||
this.isFlushing = true;
|
||||
try {
|
||||
while (this.pendingNotifications.size > 0) {
|
||||
const pending = [...this.pendingNotifications];
|
||||
this.pendingNotifications.clear();
|
||||
for (const sp of pending) {
|
||||
await sp.notifyChange();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.isFlushing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,6 +92,7 @@ export class Smartstate<StatePartNameType extends string> {
|
||||
`State part '${statePartNameArg}' already exists, but initMode is 'mandatory'`
|
||||
);
|
||||
case 'force':
|
||||
existingStatePart.dispose();
|
||||
break;
|
||||
case 'soft':
|
||||
case 'persistent':
|
||||
@@ -91,7 +100,7 @@ export class Smartstate<StatePartNameType extends string> {
|
||||
return existingStatePart as StatePart<StatePartNameType, PayloadType>;
|
||||
}
|
||||
} else {
|
||||
if (!initialArg) {
|
||||
if (initialArg === undefined) {
|
||||
throw new Error(
|
||||
`State part '${statePartNameArg}' does not exist and no initial state provided`
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user