async-reactivity 2.0.18 → 2.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/computed.js CHANGED
@@ -82,7 +82,7 @@ export default class Computed extends Tracker {
82
82
  }
83
83
  clearDependencies() {
84
84
  for (const dependency of this.dependencies.keys()) {
85
- dependency.removeDependent(this);
85
+ dependency.removeDependent(this, this.computePromise);
86
86
  }
87
87
  this.dependencies.clear();
88
88
  }
package/lib/listener.js CHANGED
@@ -4,6 +4,7 @@ export default class Listener extends Ref {
4
4
  start;
5
5
  stop;
6
6
  listening = false;
7
+ lastPromise;
7
8
  constructor(_value, start, stop, isEqual = (defaultIsEqual)) {
8
9
  super(_value, isEqual);
9
10
  this.start = start;
@@ -16,13 +17,16 @@ export default class Listener extends Ref {
16
17
  this.start();
17
18
  }
18
19
  }
19
- removeDependent(dependent) {
20
+ removeDependent(dependent, promise = Promise.resolve()) {
20
21
  super.removeDependent(dependent);
21
- Promise.resolve().then(() => {
22
- if (this.dependents.size === 0) {
23
- this.listening = false;
24
- this.stop();
22
+ const currentPromise = Promise.all([promise, this.lastPromise]).finally(() => {
23
+ if (this.lastPromise === currentPromise) {
24
+ if (this.dependents.size === 0) {
25
+ this.listening = false;
26
+ this.stop();
27
+ }
25
28
  }
26
29
  });
30
+ this.lastPromise = currentPromise;
27
31
  }
28
32
  }
@@ -75,4 +75,24 @@ describe('listener', function () {
75
75
  b.value;
76
76
  assert.strictEqual(gate, 1);
77
77
  });
78
+ it('keep listening when recomputing async', async function () {
79
+ let gate = 0;
80
+ const listener = new Listener(1, () => {
81
+ gate++;
82
+ }, () => { });
83
+ const a = new Ref(5);
84
+ const b = new Computed(async (value) => {
85
+ await new Promise(resolve => setTimeout(resolve, 50));
86
+ return value(a) + value(listener);
87
+ });
88
+ const c = new Watcher(listener, () => { });
89
+ b.value;
90
+ await new Promise(resolve => setTimeout(resolve, 100));
91
+ assert.strictEqual(gate, 1);
92
+ a.value = 6;
93
+ b.value;
94
+ c.dispose();
95
+ await new Promise(resolve => setTimeout(resolve, 100));
96
+ assert.strictEqual(gate, 1);
97
+ });
78
98
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "async-reactivity",
3
- "version": "2.0.18",
3
+ "version": "2.0.19",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "types": "types/index.d.ts",
package/src/computed.ts CHANGED
@@ -21,7 +21,7 @@ export default class Computed<T extends TBase, TBase = T> extends Tracker<T> imp
21
21
  isEqual: typeof defaultIsEqual<TBase>;
22
22
  private state = ComputedState.Invalid;
23
23
  private dependencies = new Map<Dependency<any>, boolean>();
24
- private computePromise?: T;
24
+ private computePromise?: Promise<any>;
25
25
  private computePromiseActions?: { resolve: Function, reject: Function };
26
26
  private lastComputeAttemptPromise?: Promise<void>;
27
27
 
@@ -38,7 +38,7 @@ export default class Computed<T extends TBase, TBase = T> extends Tracker<T> imp
38
38
  resolve,
39
39
  reject
40
40
  };
41
- }) as unknown as T;
41
+ });
42
42
  }
43
43
 
44
44
  public get value(): T {
@@ -83,7 +83,7 @@ export default class Computed<T extends TBase, TBase = T> extends Tracker<T> imp
83
83
  .then(result => this.handlePromiseThen(computeAttemptPromise, result))
84
84
  .catch(error => this.handlePromiseCatch(computeAttemptPromise, error)) as Promise<void>;
85
85
  this.lastComputeAttemptPromise = computeAttemptPromise;
86
- this._value = this.computePromise!;
86
+ this._value = this.computePromise! as T;
87
87
  } else {
88
88
  this._value = newValue;
89
89
  this.handlePromiseThen(this.lastComputeAttemptPromise!, this._value);
@@ -93,7 +93,7 @@ export default class Computed<T extends TBase, TBase = T> extends Tracker<T> imp
93
93
 
94
94
  private clearDependencies() {
95
95
  for (const dependency of this.dependencies.keys()) {
96
- dependency.removeDependent(this);
96
+ dependency.removeDependent(this, this.computePromise);
97
97
  }
98
98
  this.dependencies.clear();
99
99
  }
package/src/dependency.ts CHANGED
@@ -3,5 +3,5 @@ import Dependent from "./dependent.js";
3
3
  export default interface Dependency<T> {
4
4
  get value(): T;
5
5
  addDependent(dependent: Dependent): void;
6
- removeDependent(dependent: Dependent): void;
6
+ removeDependent(dependent: Dependent, promise?: Promise<any>): void;
7
7
  }
@@ -120,4 +120,34 @@ describe('listener', function () {
120
120
  b.value;
121
121
  assert.strictEqual(gate, 1);
122
122
  });
123
+
124
+ it('keep listening when recomputing async', async function() {
125
+ let gate = 0;
126
+ const listener = new Listener(
127
+ 1,
128
+ () => {
129
+ gate++;
130
+ },
131
+ () => {}
132
+ );
133
+
134
+ const a = new Ref(5);
135
+
136
+ const b = new Computed(async value => {
137
+ await new Promise(resolve => setTimeout(resolve, 50));
138
+ return value(a) + value(listener);
139
+ });
140
+
141
+ const c = new Watcher(listener, () => {});
142
+
143
+ b.value;
144
+ await new Promise(resolve => setTimeout(resolve, 100));
145
+ assert.strictEqual(gate, 1);
146
+
147
+ a.value = 6;
148
+ b.value;
149
+ c.dispose();
150
+ await new Promise(resolve => setTimeout(resolve, 100));
151
+ assert.strictEqual(gate, 1);
152
+ });
123
153
  });
package/src/listener.ts CHANGED
@@ -6,6 +6,7 @@ export default class Listener<T extends TBase, TBase = T> extends Ref<T> {
6
6
  private start: () => void;
7
7
  private stop: () => void;
8
8
  private listening = false;
9
+ private lastPromise: Promise<any> | undefined;
9
10
 
10
11
  constructor(_value: T, start: () => void, stop: () => void, isEqual = defaultIsEqual<TBase>) {
11
12
  super(_value, isEqual);
@@ -22,13 +23,17 @@ export default class Listener<T extends TBase, TBase = T> extends Ref<T> {
22
23
  }
23
24
  }
24
25
 
25
- public removeDependent(dependent: Dependent): void {
26
+ public removeDependent(dependent: Dependent, promise = Promise.resolve()): void {
26
27
  super.removeDependent(dependent);
27
- Promise.resolve().then(() => {
28
- if (this.dependents.size === 0) {
29
- this.listening = false;
30
- this.stop();
28
+
29
+ const currentPromise = Promise.all([promise, this.lastPromise]).finally(() => {
30
+ if (this.lastPromise === currentPromise) {
31
+ if (this.dependents.size === 0) {
32
+ this.listening = false;
33
+ this.stop();
34
+ }
31
35
  }
32
- })
36
+ });
37
+ this.lastPromise = currentPromise;
33
38
  }
34
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAEjD,MAAM,CAAC,OAAO,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACrE,MAAM,CAAC,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;AACjF,MAAM,CAAC,OAAO,MAAM,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;AAWzG,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,SAAS,KAAK,EAAE,KAAK,GAAG,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAE,YAAW,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5G,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,YAAY,CAAuC;IAC3D,OAAO,CAAC,cAAc,CAAC,CAAI;IAC3B,OAAO,CAAC,qBAAqB,CAAC,CAA0C;IACxE,OAAO,CAAC,yBAAyB,CAAC,CAAgB;gBAEtC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,oCAAwB;IAOnE,OAAO,CAAC,qBAAqB;IAS7B,IAAW,KAAK,IAAI,CAAC,CAMpB;IAED,OAAO,CAAC,OAAO;IA0Cf,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,eAAe,CAAwC;IAE/D,OAAO,CAAC,iBAAiB;IAMlB,UAAU;IAUV,eAAe;IAKf,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC;IAI3C,OAAO,CAAC,kBAAkB;IAMnB,OAAO;CAOjB"}
1
+ {"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAEjD,MAAM,CAAC,OAAO,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACrE,MAAM,CAAC,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;AACjF,MAAM,CAAC,OAAO,MAAM,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;AAWzG,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,SAAS,KAAK,EAAE,KAAK,GAAG,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAE,YAAW,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5G,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,YAAY,CAAuC;IAC3D,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAA0C;IACxE,OAAO,CAAC,yBAAyB,CAAC,CAAgB;gBAEtC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,oCAAwB;IAOnE,OAAO,CAAC,qBAAqB;IAS7B,IAAW,KAAK,IAAI,CAAC,CAMpB;IAED,OAAO,CAAC,OAAO;IA0Cf,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,eAAe,CAAwC;IAE/D,OAAO,CAAC,iBAAiB;IAMlB,UAAU;IAUV,eAAe;IAKf,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC;IAI3C,OAAO,CAAC,kBAAkB;IAMnB,OAAO;CAOjB"}
@@ -2,6 +2,6 @@ import Dependent from "./dependent.js";
2
2
  export default interface Dependency<T> {
3
3
  get value(): T;
4
4
  addDependent(dependent: Dependent): void;
5
- removeDependent(dependent: Dependent): void;
5
+ removeDependent(dependent: Dependent, promise?: Promise<any>): void;
6
6
  }
7
7
  //# sourceMappingURL=dependency.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dependency.d.ts","sourceRoot":"","sources":["../src/dependency.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AAEvC,MAAM,CAAC,OAAO,WAAW,UAAU,CAAC,CAAC;IACjC,IAAI,KAAK,IAAI,CAAC,CAAC;IACf,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IACzC,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;CAC/C"}
1
+ {"version":3,"file":"dependency.d.ts","sourceRoot":"","sources":["../src/dependency.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AAEvC,MAAM,CAAC,OAAO,WAAW,UAAU,CAAC,CAAC;IACjC,IAAI,KAAK,IAAI,CAAC,CAAC;IACf,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IACzC,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;CACvE"}
@@ -4,8 +4,9 @@ export default class Listener<T extends TBase, TBase = T> extends Ref<T> {
4
4
  private start;
5
5
  private stop;
6
6
  private listening;
7
+ private lastPromise;
7
8
  constructor(_value: T, start: () => void, stop: () => void, isEqual?: (v1: TBase, v2: TBase) => boolean);
8
9
  addDependent(dependent: Dependent): void;
9
- removeDependent(dependent: Dependent): void;
10
+ removeDependent(dependent: Dependent, promise?: Promise<void>): void;
10
11
  }
11
12
  //# sourceMappingURL=listener.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../src/listener.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,GAAG,MAAM,UAAU,CAAC;AAG3B,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,SAAS,KAAK,EAAE,KAAK,GAAG,CAAC,CAAE,SAAQ,GAAG,CAAC,CAAC,CAAC;IACpE,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,IAAI,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE,OAAO,oCAAwB;IAOpF,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAQxC,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;CASrD"}
1
+ {"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../src/listener.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,GAAG,MAAM,UAAU,CAAC;AAG3B,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,SAAS,KAAK,EAAE,KAAK,GAAG,CAAC,CAAE,SAAQ,GAAG,CAAC,CAAC,CAAC;IACpE,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAA2B;gBAElC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,IAAI,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE,OAAO,oCAAwB;IAOpF,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAQxC,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,gBAAoB,GAAG,IAAI;CAalF"}