[REF] observer: move batch code out of store, add notifycb

This commit is contained in:
Géry Debongnie
2019-04-17 09:16:19 +02:00
parent c47c4ccc60
commit 94e7d9aa39
3 changed files with 44 additions and 14 deletions
+16 -3
View File
@@ -18,7 +18,7 @@ const ModifiedArrayProto = Object.create(ArrayProto);
for (let method of methodsToPatch) { for (let method of methodsToPatch) {
const initialMethod = ArrayProto[method]; const initialMethod = ArrayProto[method];
ModifiedArrayProto[method] = function(...args) { ModifiedArrayProto[method] = function(...args) {
this.__observer__.rev++; this.__observer__.notifyChange();
this.__owl__.rev++; this.__owl__.rev++;
let parent = this; let parent = this;
do { do {
@@ -46,6 +46,19 @@ for (let method of methodsToPatch) {
export class Observer { export class Observer {
rev: number = 1; rev: number = 1;
allowMutations: boolean = true; allowMutations: boolean = true;
dirty: boolean = false;
notifyCB() {}
notifyChange() {
this.rev++;
this.dirty = true;
Promise.resolve().then(() => {
if (this.dirty) {
this.dirty = false;
this.notifyCB();
}
});
}
observe(value: any, parent?: any) { observe(value: any, parent?: any) {
if (value === null) { if (value === null) {
@@ -69,7 +82,7 @@ export class Observer {
set(target: any, key: number | string, value: any) { set(target: any, key: number | string, value: any) {
this._addProp(target, key, value); this._addProp(target, key, value);
target.__owl__.rev++; target.__owl__.rev++;
this.rev++; this.notifyChange();
} }
unobserve(target: any) { unobserve(target: any) {
@@ -119,11 +132,11 @@ export class Observer {
value = newVal; value = newVal;
self.observe(newVal, obj); self.observe(newVal, obj);
obj.__owl__.rev!++; obj.__owl__.rev!++;
self.rev++;
let parent = obj; let parent = obj;
do { do {
parent.__owl__.deepRev++; parent.__owl__.deepRev++;
} while ((parent = parent.__owl__.parent)); } while ((parent = parent.__owl__.parent));
self.notifyChange();
} }
} }
}); });
+1 -11
View File
@@ -22,7 +22,6 @@ export class Store extends EventBus {
actions: any; actions: any;
mutations: any; mutations: any;
_commitLevel: number = 0; _commitLevel: number = 0;
_isMutating: boolean = false;
history: any[] = []; history: any[] = [];
debug: boolean; debug: boolean;
env: any; env: any;
@@ -37,6 +36,7 @@ export class Store extends EventBus {
this.mutations = config.mutations; this.mutations = config.mutations;
this.env = config.env; this.env = config.env;
this.observer = new Observer(); this.observer = new Observer();
this.observer.notifyCB = this.trigger.bind(this, "update");
this.observer.allowMutations = false; this.observer.allowMutations = false;
this.observer.observe(this.state); this.observer.observe(this.state);
@@ -72,8 +72,6 @@ export class Store extends EventBus {
throw new Error(`[Error] mutation ${type} is undefined`); throw new Error(`[Error] mutation ${type} is undefined`);
} }
this._commitLevel++; this._commitLevel++;
const currentRev = this.observer.rev;
this._isMutating = true;
this.observer.allowMutations = true; this.observer.allowMutations = true;
const res = this.mutations[type].call( const res = this.mutations[type].call(
@@ -95,14 +93,6 @@ export class Store extends EventBus {
payload: payload payload: payload
}); });
} }
Promise.resolve().then(() => {
if (this._isMutating) {
this._isMutating = false;
if (currentRev !== this.observer.rev) {
this.trigger("update", this.state);
}
}
});
} }
this._commitLevel--; this._commitLevel--;
return res; return res;
+27
View File
@@ -1,4 +1,5 @@
import { Observer } from "../src/observer"; import { Observer } from "../src/observer";
import { nextMicroTick } from "./helpers";
describe("observer", () => { describe("observer", () => {
test("properly observe objects", () => { test("properly observe objects", () => {
@@ -252,4 +253,30 @@ describe("observer", () => {
expect(obj1.__owl__.rev).toBe(1); expect(obj1.__owl__.rev).toBe(1);
expect(obj2.__owl__.rev).toBe(2); expect(obj2.__owl__.rev).toBe(2);
}); });
test("call callback when state is changed", async () => {
const observer = new Observer();
observer.notifyCB = jest.fn();
const obj: any = { a: 1, b: { c: 2 }, d: [{ e: 3 }], f: 4 };
observer.observe(obj);
expect(observer.notifyCB).toBeCalledTimes(0);
obj.a = 2;
await nextMicroTick();
expect(observer.notifyCB).toBeCalledTimes(1);
obj.b.c = 3;
await nextMicroTick();
expect(observer.notifyCB).toBeCalledTimes(2);
obj.d[0].e = 5;
await nextMicroTick();
expect(observer.notifyCB).toBeCalledTimes(3);
obj.a = 111;
obj.f = 222;
await nextMicroTick();
expect(observer.notifyCB).toBeCalledTimes(4);
});
}); });