async-reactivity 2.2.1 → 2.2.3
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 +21 -15
- package/lib/computed.test.js +28 -0
- package/package.json +4 -4
- package/src/computed.test.ts +33 -2
- package/src/computed.ts +21 -15
- package/types/computed.d.ts.map +1 -1
package/lib/computed.js
CHANGED
|
@@ -29,23 +29,28 @@ export default class Computed extends Effect {
|
|
|
29
29
|
if (this.state === EffectState.Initial || this.state === EffectState.Scheduled) {
|
|
30
30
|
this.oldValue = this._value;
|
|
31
31
|
const newValue = this.run();
|
|
32
|
-
if (newValue
|
|
33
|
-
|
|
32
|
+
if (newValue instanceof Promise) {
|
|
33
|
+
// @ts-expect-error
|
|
34
|
+
this._value = Promise.allSettled([newValue, this.oldValue])
|
|
35
|
+
.then(([newValueResult, oldValueResult]) => {
|
|
36
|
+
const newValue = newValueResult.status === 'fulfilled' ? newValueResult.value : newValueResult.reason;
|
|
37
|
+
const oldValue = oldValueResult.status === 'fulfilled' ? oldValueResult.value : oldValueResult.reason;
|
|
38
|
+
if (newValue === InSyncSymbol) {
|
|
39
|
+
this.validateDependents();
|
|
40
|
+
return oldValue;
|
|
41
|
+
}
|
|
42
|
+
if (this.dependents.size > 0 && newValueResult.status === oldValueResult.status && this.isEqual(newValue, oldValue)) {
|
|
43
|
+
this.validateDependents();
|
|
44
|
+
}
|
|
45
|
+
if (this.state === EffectState.Waiting) {
|
|
46
|
+
this.oldValue = undefined;
|
|
47
|
+
}
|
|
48
|
+
return newValueResult.status === 'fulfilled' ? newValue : Promise.reject(newValue);
|
|
49
|
+
});
|
|
34
50
|
}
|
|
35
51
|
else {
|
|
36
|
-
if (newValue
|
|
37
|
-
|
|
38
|
-
this._value = Promise.all([newValue, this.oldValue])
|
|
39
|
-
.then(([newValue, oldValue]) => {
|
|
40
|
-
if (newValue === InSyncSymbol) {
|
|
41
|
-
this.validateDependents();
|
|
42
|
-
return oldValue;
|
|
43
|
-
}
|
|
44
|
-
if (this.dependents.size > 0 && this.isEqual(newValue, oldValue)) {
|
|
45
|
-
this.validateDependents();
|
|
46
|
-
}
|
|
47
|
-
return newValue;
|
|
48
|
-
});
|
|
52
|
+
if (newValue === InSyncSymbol) {
|
|
53
|
+
this.validateDependents();
|
|
49
54
|
}
|
|
50
55
|
else {
|
|
51
56
|
this._value = newValue;
|
|
@@ -53,6 +58,7 @@ export default class Computed extends Effect {
|
|
|
53
58
|
this.validateDependents();
|
|
54
59
|
}
|
|
55
60
|
}
|
|
61
|
+
this.oldValue = undefined;
|
|
56
62
|
}
|
|
57
63
|
}
|
|
58
64
|
return this._value;
|
package/lib/computed.test.js
CHANGED
|
@@ -70,6 +70,18 @@ describe('computed', function () {
|
|
|
70
70
|
});
|
|
71
71
|
assert.throws(() => a.value);
|
|
72
72
|
});
|
|
73
|
+
it('recompute after error', function () {
|
|
74
|
+
const a = new Ref(5);
|
|
75
|
+
const b = new Computed((value) => {
|
|
76
|
+
if (value(a) === 5) {
|
|
77
|
+
throw new Error();
|
|
78
|
+
}
|
|
79
|
+
return value(a);
|
|
80
|
+
});
|
|
81
|
+
assert.throws(() => b.value);
|
|
82
|
+
a.value = 6;
|
|
83
|
+
assert.strictEqual(b.value, 6);
|
|
84
|
+
});
|
|
73
85
|
it('ignore same ref value', function () {
|
|
74
86
|
let gate = 0;
|
|
75
87
|
const a = new Ref(5);
|
|
@@ -208,6 +220,22 @@ describe('computed', function () {
|
|
|
208
220
|
a.value;
|
|
209
221
|
assert.strictEqual(await a.value, 5);
|
|
210
222
|
});
|
|
223
|
+
it('recompute after error', async function () {
|
|
224
|
+
const a = new Ref(5);
|
|
225
|
+
const b = new Computed(async (value) => {
|
|
226
|
+
if (value(a) === 5) {
|
|
227
|
+
throw new Error();
|
|
228
|
+
}
|
|
229
|
+
return value(a);
|
|
230
|
+
});
|
|
231
|
+
try {
|
|
232
|
+
await b.value;
|
|
233
|
+
}
|
|
234
|
+
catch { }
|
|
235
|
+
a.value = 6;
|
|
236
|
+
console.log('invalidate');
|
|
237
|
+
assert.strictEqual(await b.value, 6);
|
|
238
|
+
});
|
|
211
239
|
it('detect circular dependency', async function () {
|
|
212
240
|
// @ts-expect-error
|
|
213
241
|
const a = new Computed(async (value) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "async-reactivity",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/lodash-es": "^4.17.12",
|
|
26
26
|
"@types/mocha": "^10.0.10",
|
|
27
|
-
"@types/node": "^24.
|
|
28
|
-
"mocha": "^11.7.
|
|
27
|
+
"@types/node": "^24.13.2",
|
|
28
|
+
"mocha": "^11.7.6",
|
|
29
29
|
"typescript": "^5.9.3"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"lodash-es": "^4.
|
|
32
|
+
"lodash-es": "^4.18.1"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/computed.test.ts
CHANGED
|
@@ -83,6 +83,20 @@ describe('computed', function () {
|
|
|
83
83
|
assert.throws(() => a.value);
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
+
it('recompute after error', function () {
|
|
87
|
+
const a = new Ref(5);
|
|
88
|
+
const b = new Computed((value) => {
|
|
89
|
+
if (value(a) === 5) {
|
|
90
|
+
throw new Error();
|
|
91
|
+
}
|
|
92
|
+
return value(a);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
assert.throws(() => b.value);
|
|
96
|
+
a.value = 6;
|
|
97
|
+
assert.strictEqual(b.value, 6);
|
|
98
|
+
});
|
|
99
|
+
|
|
86
100
|
it('ignore same ref value', function () {
|
|
87
101
|
let gate = 0;
|
|
88
102
|
const a = new Ref(5);
|
|
@@ -137,7 +151,7 @@ describe('computed', function () {
|
|
|
137
151
|
assert.strictEqual(gate, 1);
|
|
138
152
|
});
|
|
139
153
|
|
|
140
|
-
it('ignore in sync dependencies', function() {
|
|
154
|
+
it('ignore in sync dependencies', function () {
|
|
141
155
|
let gate = 0;
|
|
142
156
|
const a = new Ref(5);
|
|
143
157
|
const b = new Computed((value) => {
|
|
@@ -248,6 +262,23 @@ describe('computed', function () {
|
|
|
248
262
|
assert.strictEqual(await a.value, 5);
|
|
249
263
|
});
|
|
250
264
|
|
|
265
|
+
it('recompute after error', async function () {
|
|
266
|
+
const a = new Ref(5);
|
|
267
|
+
const b = new Computed(async (value) => {
|
|
268
|
+
if (value(a) === 5) {
|
|
269
|
+
throw new Error();
|
|
270
|
+
}
|
|
271
|
+
return value(a);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
try {
|
|
275
|
+
await b.value;
|
|
276
|
+
} catch { }
|
|
277
|
+
a.value = 6;
|
|
278
|
+
console.log('invalidate');
|
|
279
|
+
assert.strictEqual(await b.value, 6);
|
|
280
|
+
});
|
|
281
|
+
|
|
251
282
|
it('detect circular dependency', async function () {
|
|
252
283
|
// @ts-expect-error
|
|
253
284
|
const a = new Computed(async (value) => {
|
|
@@ -391,7 +422,7 @@ describe('computed', function () {
|
|
|
391
422
|
assert.strictEqual(gate, 1);
|
|
392
423
|
});
|
|
393
424
|
|
|
394
|
-
it('ignore in sync dependencies', async function() {
|
|
425
|
+
it('ignore in sync dependencies', async function () {
|
|
395
426
|
let gate = 0;
|
|
396
427
|
const a = new Ref(5);
|
|
397
428
|
const b = new Computed(async (value) => {
|
package/src/computed.ts
CHANGED
|
@@ -41,28 +41,34 @@ export default class Computed<T> extends Effect implements Dependent, Dependency
|
|
|
41
41
|
if (this.state === EffectState.Initial || this.state === EffectState.Scheduled) {
|
|
42
42
|
this.oldValue = this._value!;
|
|
43
43
|
const newValue = this.run() as T;
|
|
44
|
-
if (newValue
|
|
45
|
-
|
|
44
|
+
if (newValue instanceof Promise) {
|
|
45
|
+
// @ts-expect-error
|
|
46
|
+
this._value = Promise.allSettled([newValue, this.oldValue])
|
|
47
|
+
.then(([newValueResult, oldValueResult]) => {
|
|
48
|
+
const newValue = newValueResult.status === 'fulfilled' ? newValueResult.value : newValueResult.reason;
|
|
49
|
+
const oldValue = oldValueResult.status === 'fulfilled' ? oldValueResult.value : oldValueResult.reason;
|
|
50
|
+
if (newValue === InSyncSymbol) {
|
|
51
|
+
this.validateDependents();
|
|
52
|
+
return oldValue;
|
|
53
|
+
}
|
|
54
|
+
if (this.dependents.size > 0 && newValueResult.status === oldValueResult.status && this.isEqual(newValue, oldValue)) {
|
|
55
|
+
this.validateDependents();
|
|
56
|
+
}
|
|
57
|
+
if (this.state === EffectState.Waiting) {
|
|
58
|
+
this.oldValue = undefined;
|
|
59
|
+
}
|
|
60
|
+
return newValueResult.status === 'fulfilled' ? newValue : Promise.reject(newValue);
|
|
61
|
+
});
|
|
46
62
|
} else {
|
|
47
|
-
if (newValue
|
|
48
|
-
|
|
49
|
-
this._value = Promise.all([newValue, this.oldValue])
|
|
50
|
-
.then(([newValue, oldValue]) => {
|
|
51
|
-
if (newValue === InSyncSymbol) {
|
|
52
|
-
this.validateDependents();
|
|
53
|
-
return oldValue;
|
|
54
|
-
}
|
|
55
|
-
if (this.dependents.size > 0 && this.isEqual(newValue, oldValue)) {
|
|
56
|
-
this.validateDependents();
|
|
57
|
-
}
|
|
58
|
-
return newValue;
|
|
59
|
-
});
|
|
63
|
+
if (newValue === InSyncSymbol) {
|
|
64
|
+
this.validateDependents();
|
|
60
65
|
} else {
|
|
61
66
|
this._value = newValue;
|
|
62
67
|
if (this.dependents.size > 0 && this.isEqual(newValue, this.oldValue)) {
|
|
63
68
|
this.validateDependents();
|
|
64
69
|
}
|
|
65
70
|
}
|
|
71
|
+
this.oldValue = undefined;
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
74
|
|
package/types/computed.d.ts.map
CHANGED
|
@@ -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,cAAc,MAAM,qBAAqB,CAAC;AAGjD,OAAO,MAAqC,MAAM,aAAa,CAAC;AAEhE,MAAM,CAAC,OAAO,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,KAAK,CAAC,GAAG,SAAS,CAAC,CAAC;AACvI,MAAM,CAAC,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,GAAG,SAAS,EAAE,WAAW,EAAE,WAAW,KAAK,CAAC,CAAC;AACtH,MAAM,CAAC,OAAO,MAAM,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,GAAG,SAAS,EAAE,WAAW,EAAE,WAAW,KAAK,EAAE,CAAC;AAI9I,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,CAAE,SAAQ,MAAO,YAAW,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAC/E,OAAO,CAAC,QAAQ,CAAC,CAAI;IACrB,OAAO,CAAC,MAAM,CAAC,CAAI;IACnB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,QAAQ,CAAC,CAAW;gBAEhB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,4BAAoB,EAAE,UAAU,CAAC,EAAE,MAAM;IAkBpF,IAAW,KAAK,IAAI,CAAC,
|
|
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,cAAc,MAAM,qBAAqB,CAAC;AAGjD,OAAO,MAAqC,MAAM,aAAa,CAAC;AAEhE,MAAM,CAAC,OAAO,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,KAAK,CAAC,GAAG,SAAS,CAAC,CAAC;AACvI,MAAM,CAAC,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,GAAG,SAAS,EAAE,WAAW,EAAE,WAAW,KAAK,CAAC,CAAC;AACtH,MAAM,CAAC,OAAO,MAAM,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,GAAG,SAAS,EAAE,WAAW,EAAE,WAAW,KAAK,EAAE,CAAC;AAI9I,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,CAAE,SAAQ,MAAO,YAAW,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAC/E,OAAO,CAAC,QAAQ,CAAC,CAAI;IACrB,OAAO,CAAC,MAAM,CAAC,CAAI;IACnB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,QAAQ,CAAC,CAAW;gBAEhB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,4BAAoB,EAAE,UAAU,CAAC,EAAE,MAAM;IAkBpF,IAAW,KAAK,IAAI,CAAC,CAoCpB;IAED,OAAO,CAAC,kBAAkB;IAMnB,YAAY,CAAC,SAAS,EAAE,SAAS;IAOjC,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,gBAAoB,GAAG,IAAI;IAKxE,UAAU,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC;IAW3C,eAAe;IAaf,KAAK;IAKL,OAAO;CAGjB"}
|