proxy-facades 1.3.0 → 1.5.0
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/dist/commonjs/retsync.d.ts +15 -0
- package/dist/commonjs/retsync.d.ts.map +1 -1
- package/dist/commonjs/retsync.js +48 -16
- package/dist/commonjs/retsync.js.map +1 -1
- package/dist/esm/retsync.d.ts +15 -0
- package/dist/esm/retsync.d.ts.map +1 -1
- package/dist/esm/retsync.js +46 -15
- package/dist/esm/retsync.js.map +1 -1
- package/package.json +1 -1
- package/retsync.ts +50 -16
|
@@ -4,6 +4,20 @@ type Retsync2promiseOptions = {
|
|
|
4
4
|
*/
|
|
5
5
|
checkSaved?: boolean;
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* Internal / used in frameworks.
|
|
9
|
+
*/
|
|
10
|
+
export declare class Retsync2promiseCall {
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Global state. Internal / shared with frameworks.
|
|
14
|
+
*/
|
|
15
|
+
export declare const _global: {
|
|
16
|
+
resolvedPromiseValues: WeakMap<Promise<any>, unknown>;
|
|
17
|
+
retsync2promiseCall?: Retsync2promiseCall;
|
|
18
|
+
globalObj: {};
|
|
19
|
+
resourcePromises: import("./Util").DefaultMap<unknown, Map<string | number | undefined, Promise<unknown>>>;
|
|
20
|
+
};
|
|
7
21
|
/**
|
|
8
22
|
* Let's you run retsync code and wait, till it is finished.
|
|
9
23
|
* @param repeatableFn
|
|
@@ -26,6 +40,7 @@ export declare function promise2retsync<T>(savedPromise: Promise<T>): T;
|
|
|
26
40
|
* @param loaderFn
|
|
27
41
|
* @param idObj object to associate this call to. undefined means globally and the idKey primitive value is the only key.
|
|
28
42
|
* @param idKey Additional primitive key under idObj.
|
|
43
|
+
* @see cleanResource
|
|
29
44
|
*/
|
|
30
45
|
export declare function asyncResource2retsync<T>(loaderFn: () => Promise<T>, idObj: object | undefined, idKey?: (string | number)): T;
|
|
31
46
|
export declare class RetsyncWaitsForPromiseException extends Error {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retsync.d.ts","sourceRoot":"","sources":["../../retsync.ts"],"names":[],"mappings":"AASA,KAAK,sBAAsB,GAAG;IAC1B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;
|
|
1
|
+
{"version":3,"file":"retsync.d.ts","sourceRoot":"","sources":["../../retsync.ts"],"names":[],"mappings":"AASA,KAAK,sBAAsB,GAAG;IAC1B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;AAED;;GAEG;AACH,qBAAa,mBAAmB;CAE/B;AAED;;GAEG;AACH,eAAO,MAAM,OAAO;;0BAEM,mBAAmB;;;CAG5C,CAAA;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,CAAC,CAAC,CA0DhH;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAM9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAK,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,GAAC,MAAM,CAAC,GAAG,CAAC,CAyBzH;AAqBD,qBAAa,+BAAgC,SAAQ,KAAK;IACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;gBAET,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC;CAIpC;AAED,wBAAgB,6BAA6B,SAI5C;;AAID;;GAEG"}
|
package/dist/commonjs/retsync.js
CHANGED
|
@@ -5,14 +5,28 @@
|
|
|
5
5
|
// Semantics: Retsync code must be repeatable. It can change state, as long as that leads to the same result when repeated.
|
|
6
6
|
// It does not mean strictly deterministic (may be for while in the same sync block??) because resources that are fetched, can change over time. Therefore some inner user's retsync code might subscribe to change events and invalidate asyncResource2retsync's cached promises when there are such changes.
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.RetsyncWaitsForPromiseException = void 0;
|
|
8
|
+
exports.RetsyncWaitsForPromiseException = exports._global = exports.Retsync2promiseCall = void 0;
|
|
9
9
|
exports.retsync2promise = retsync2promise;
|
|
10
10
|
exports.promise2retsync = promise2retsync;
|
|
11
11
|
exports.asyncResource2retsync = asyncResource2retsync;
|
|
12
12
|
exports.checkThatCallerHandlesRetsync = checkThatCallerHandlesRetsync;
|
|
13
13
|
const Util_1 = require("./Util");
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Internal / used in frameworks.
|
|
16
|
+
*/
|
|
17
|
+
class Retsync2promiseCall {
|
|
18
|
+
}
|
|
19
|
+
exports.Retsync2promiseCall = Retsync2promiseCall;
|
|
20
|
+
/**
|
|
21
|
+
* Global state. Internal / shared with frameworks.
|
|
22
|
+
*/
|
|
23
|
+
exports._global = new class {
|
|
24
|
+
constructor() {
|
|
25
|
+
this.resolvedPromiseValues = new WeakMap();
|
|
26
|
+
this.globalObj = {};
|
|
27
|
+
this.resourcePromises = (0, Util_1.newDefaultWeakMap)((key) => new Map());
|
|
28
|
+
}
|
|
29
|
+
};
|
|
16
30
|
/**
|
|
17
31
|
* Let's you run retsync code and wait, till it is finished.
|
|
18
32
|
* @param repeatableFn
|
|
@@ -20,16 +34,16 @@ let callerHandlesRetsync = false;
|
|
|
20
34
|
*/
|
|
21
35
|
async function retsync2promise(repeatableFn, options = {}) {
|
|
22
36
|
/**
|
|
23
|
-
* ...while
|
|
37
|
+
* ...while indicating that it is being called
|
|
24
38
|
*/
|
|
25
39
|
function runRepeatableFn() {
|
|
26
|
-
const
|
|
40
|
+
const orig_retsync2promiseCall = exports._global.retsync2promiseCall;
|
|
27
41
|
try {
|
|
28
|
-
|
|
42
|
+
exports._global.retsync2promiseCall = new Retsync2promiseCall();
|
|
29
43
|
return repeatableFn();
|
|
30
44
|
}
|
|
31
45
|
finally {
|
|
32
|
-
|
|
46
|
+
exports._global.retsync2promiseCall = orig_retsync2promiseCall;
|
|
33
47
|
}
|
|
34
48
|
}
|
|
35
49
|
while (true) {
|
|
@@ -37,7 +51,7 @@ async function retsync2promise(repeatableFn, options = {}) {
|
|
|
37
51
|
return runRepeatableFn();
|
|
38
52
|
}
|
|
39
53
|
catch (e) {
|
|
40
|
-
if (e instanceof RetsyncWaitsForPromiseException) {
|
|
54
|
+
if (e != null && e instanceof RetsyncWaitsForPromiseException) {
|
|
41
55
|
if (e.checkSaved || (e.checkSaved === undefined && options.checkSaved !== false)) {
|
|
42
56
|
const optionHint = `Hint: See also: Retsync2promiseOptions#checkSaved`;
|
|
43
57
|
// Check if repeatableFn is behaving in repeatable symantics and saves the promise
|
|
@@ -59,7 +73,7 @@ async function retsync2promise(repeatableFn, options = {}) {
|
|
|
59
73
|
}
|
|
60
74
|
}
|
|
61
75
|
}
|
|
62
|
-
resolvedPromiseValues.set(e.promise, await e.promise);
|
|
76
|
+
exports._global.resolvedPromiseValues.set(e.promise, await e.promise);
|
|
63
77
|
// Try again. Now it will hit the resolved value
|
|
64
78
|
}
|
|
65
79
|
else {
|
|
@@ -80,13 +94,11 @@ async function retsync2promise(repeatableFn, options = {}) {
|
|
|
80
94
|
* @param savedPromise You must save/fix the promise somewhere, so you reuse it the next time you encounter it.
|
|
81
95
|
*/
|
|
82
96
|
function promise2retsync(savedPromise) {
|
|
83
|
-
if (resolvedPromiseValues.has(savedPromise)) {
|
|
84
|
-
return resolvedPromiseValues.get(savedPromise);
|
|
97
|
+
if (exports._global.resolvedPromiseValues.has(savedPromise)) {
|
|
98
|
+
return exports._global.resolvedPromiseValues.get(savedPromise);
|
|
85
99
|
}
|
|
86
100
|
throw new RetsyncWaitsForPromiseException(savedPromise);
|
|
87
101
|
}
|
|
88
|
-
const globalObj = {};
|
|
89
|
-
const resourcePromises = (0, Util_1.newDefaultWeakMap)((key) => new Map());
|
|
90
102
|
/**
|
|
91
103
|
* Makes async code usable in retsync code.
|
|
92
104
|
* <p>
|
|
@@ -98,10 +110,15 @@ const resourcePromises = (0, Util_1.newDefaultWeakMap)((key) => new Map());
|
|
|
98
110
|
* @param loaderFn
|
|
99
111
|
* @param idObj object to associate this call to. undefined means globally and the idKey primitive value is the only key.
|
|
100
112
|
* @param idKey Additional primitive key under idObj.
|
|
113
|
+
* @see cleanResource
|
|
101
114
|
*/
|
|
102
115
|
function asyncResource2retsync(loaderFn, idObj, idKey) {
|
|
103
|
-
|
|
104
|
-
|
|
116
|
+
// Validity check:
|
|
117
|
+
if (!idObj && !idKey) {
|
|
118
|
+
throw new Error("Either idObj or idKey must be specified");
|
|
119
|
+
}
|
|
120
|
+
idObj = idObj || exports._global.globalObj;
|
|
121
|
+
const promisesForIdObj = exports._global.resourcePromises.get(idObj);
|
|
105
122
|
let promise = promisesForIdObj.get(idKey);
|
|
106
123
|
if (!promise) {
|
|
107
124
|
promise = loaderFn();
|
|
@@ -118,6 +135,21 @@ function asyncResource2retsync(loaderFn, idObj, idKey) {
|
|
|
118
135
|
throw e;
|
|
119
136
|
}
|
|
120
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Cleans the promise and therefore the result behind the given obj+key like used in {@link asyncResource2retsync}.
|
|
140
|
+
* Call this i.e. on the event that the resource has change and you want to "invalidate the cached value", so it will be fetched fresh next time.
|
|
141
|
+
* @param idObj
|
|
142
|
+
* @param idKey
|
|
143
|
+
*/
|
|
144
|
+
function cleanResource(idObj, idKey) {
|
|
145
|
+
// Validity check:
|
|
146
|
+
if (!idObj && !idKey) {
|
|
147
|
+
throw new Error("Either idObj or idKey must be specified");
|
|
148
|
+
}
|
|
149
|
+
idObj = idObj || exports._global.globalObj;
|
|
150
|
+
const promisesForIdObj = exports._global.resourcePromises.get(idObj);
|
|
151
|
+
promisesForIdObj.delete(idKey);
|
|
152
|
+
}
|
|
121
153
|
class RetsyncWaitsForPromiseException extends Error {
|
|
122
154
|
constructor(promise) {
|
|
123
155
|
super("Some retsync style code (see call stack / caller of promise2retsync) wants to await an async operation. To make this possible, you need to wrapt it at some ancestor caller level with retsync2promise. I.e. 'const result = await retsync2promise(() => {...your **retryable*** - synchronous code...}});");
|
|
@@ -126,7 +158,7 @@ class RetsyncWaitsForPromiseException extends Error {
|
|
|
126
158
|
}
|
|
127
159
|
exports.RetsyncWaitsForPromiseException = RetsyncWaitsForPromiseException;
|
|
128
160
|
function checkThatCallerHandlesRetsync() {
|
|
129
|
-
if (!
|
|
161
|
+
if (!exports._global.retsync2promiseCall) {
|
|
130
162
|
throw new Error("The method, you are calling uses retsync code and needs to be wrapped at some ancestor caller level with retsync2promise. I.e. 'const result = await retsync2promise(() => {...call the function that (deep inside) uses **retryable*** - synchronous code...}});");
|
|
131
163
|
}
|
|
132
164
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retsync.js","sourceRoot":"","sources":["../../retsync.ts"],"names":[],"mappings":";AAAA,wCAAwC;AACxC,0JAA0J;AAC1J,2CAA2C;AAC3C,2HAA2H;AAC3H,8SAA8S;;;
|
|
1
|
+
{"version":3,"file":"retsync.js","sourceRoot":"","sources":["../../retsync.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/retsync.d.ts
CHANGED
|
@@ -4,6 +4,20 @@ type Retsync2promiseOptions = {
|
|
|
4
4
|
*/
|
|
5
5
|
checkSaved?: boolean;
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* Internal / used in frameworks.
|
|
9
|
+
*/
|
|
10
|
+
export declare class Retsync2promiseCall {
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Global state. Internal / shared with frameworks.
|
|
14
|
+
*/
|
|
15
|
+
export declare const _global: {
|
|
16
|
+
resolvedPromiseValues: WeakMap<Promise<any>, unknown>;
|
|
17
|
+
retsync2promiseCall?: Retsync2promiseCall;
|
|
18
|
+
globalObj: {};
|
|
19
|
+
resourcePromises: import("./Util").DefaultMap<unknown, Map<string | number | undefined, Promise<unknown>>>;
|
|
20
|
+
};
|
|
7
21
|
/**
|
|
8
22
|
* Let's you run retsync code and wait, till it is finished.
|
|
9
23
|
* @param repeatableFn
|
|
@@ -26,6 +40,7 @@ export declare function promise2retsync<T>(savedPromise: Promise<T>): T;
|
|
|
26
40
|
* @param loaderFn
|
|
27
41
|
* @param idObj object to associate this call to. undefined means globally and the idKey primitive value is the only key.
|
|
28
42
|
* @param idKey Additional primitive key under idObj.
|
|
43
|
+
* @see cleanResource
|
|
29
44
|
*/
|
|
30
45
|
export declare function asyncResource2retsync<T>(loaderFn: () => Promise<T>, idObj: object | undefined, idKey?: (string | number)): T;
|
|
31
46
|
export declare class RetsyncWaitsForPromiseException extends Error {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retsync.d.ts","sourceRoot":"","sources":["../../retsync.ts"],"names":[],"mappings":"AASA,KAAK,sBAAsB,GAAG;IAC1B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;
|
|
1
|
+
{"version":3,"file":"retsync.d.ts","sourceRoot":"","sources":["../../retsync.ts"],"names":[],"mappings":"AASA,KAAK,sBAAsB,GAAG;IAC1B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;AAED;;GAEG;AACH,qBAAa,mBAAmB;CAE/B;AAED;;GAEG;AACH,eAAO,MAAM,OAAO;;0BAEM,mBAAmB;;;CAG5C,CAAA;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,CAAC,CAAC,CA0DhH;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAM9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAK,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,GAAC,MAAM,CAAC,GAAG,CAAC,CAyBzH;AAqBD,qBAAa,+BAAgC,SAAQ,KAAK;IACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;gBAET,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC;CAIpC;AAED,wBAAgB,6BAA6B,SAI5C;;AAID;;GAEG"}
|
package/dist/esm/retsync.js
CHANGED
|
@@ -4,8 +4,21 @@
|
|
|
4
4
|
// Semantics: Retsync code must be repeatable. It can change state, as long as that leads to the same result when repeated.
|
|
5
5
|
// It does not mean strictly deterministic (may be for while in the same sync block??) because resources that are fetched, can change over time. Therefore some inner user's retsync code might subscribe to change events and invalidate asyncResource2retsync's cached promises when there are such changes.
|
|
6
6
|
import { newDefaultWeakMap } from "./Util";
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Internal / used in frameworks.
|
|
9
|
+
*/
|
|
10
|
+
export class Retsync2promiseCall {
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Global state. Internal / shared with frameworks.
|
|
14
|
+
*/
|
|
15
|
+
export const _global = new class {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.resolvedPromiseValues = new WeakMap();
|
|
18
|
+
this.globalObj = {};
|
|
19
|
+
this.resourcePromises = newDefaultWeakMap((key) => new Map());
|
|
20
|
+
}
|
|
21
|
+
};
|
|
9
22
|
/**
|
|
10
23
|
* Let's you run retsync code and wait, till it is finished.
|
|
11
24
|
* @param repeatableFn
|
|
@@ -13,16 +26,16 @@ let callerHandlesRetsync = false;
|
|
|
13
26
|
*/
|
|
14
27
|
export async function retsync2promise(repeatableFn, options = {}) {
|
|
15
28
|
/**
|
|
16
|
-
* ...while
|
|
29
|
+
* ...while indicating that it is being called
|
|
17
30
|
*/
|
|
18
31
|
function runRepeatableFn() {
|
|
19
|
-
const
|
|
32
|
+
const orig_retsync2promiseCall = _global.retsync2promiseCall;
|
|
20
33
|
try {
|
|
21
|
-
|
|
34
|
+
_global.retsync2promiseCall = new Retsync2promiseCall();
|
|
22
35
|
return repeatableFn();
|
|
23
36
|
}
|
|
24
37
|
finally {
|
|
25
|
-
|
|
38
|
+
_global.retsync2promiseCall = orig_retsync2promiseCall;
|
|
26
39
|
}
|
|
27
40
|
}
|
|
28
41
|
while (true) {
|
|
@@ -30,7 +43,7 @@ export async function retsync2promise(repeatableFn, options = {}) {
|
|
|
30
43
|
return runRepeatableFn();
|
|
31
44
|
}
|
|
32
45
|
catch (e) {
|
|
33
|
-
if (e instanceof RetsyncWaitsForPromiseException) {
|
|
46
|
+
if (e != null && e instanceof RetsyncWaitsForPromiseException) {
|
|
34
47
|
if (e.checkSaved || (e.checkSaved === undefined && options.checkSaved !== false)) {
|
|
35
48
|
const optionHint = `Hint: See also: Retsync2promiseOptions#checkSaved`;
|
|
36
49
|
// Check if repeatableFn is behaving in repeatable symantics and saves the promise
|
|
@@ -52,7 +65,7 @@ export async function retsync2promise(repeatableFn, options = {}) {
|
|
|
52
65
|
}
|
|
53
66
|
}
|
|
54
67
|
}
|
|
55
|
-
resolvedPromiseValues.set(e.promise, await e.promise);
|
|
68
|
+
_global.resolvedPromiseValues.set(e.promise, await e.promise);
|
|
56
69
|
// Try again. Now it will hit the resolved value
|
|
57
70
|
}
|
|
58
71
|
else {
|
|
@@ -73,13 +86,11 @@ export async function retsync2promise(repeatableFn, options = {}) {
|
|
|
73
86
|
* @param savedPromise You must save/fix the promise somewhere, so you reuse it the next time you encounter it.
|
|
74
87
|
*/
|
|
75
88
|
export function promise2retsync(savedPromise) {
|
|
76
|
-
if (resolvedPromiseValues.has(savedPromise)) {
|
|
77
|
-
return resolvedPromiseValues.get(savedPromise);
|
|
89
|
+
if (_global.resolvedPromiseValues.has(savedPromise)) {
|
|
90
|
+
return _global.resolvedPromiseValues.get(savedPromise);
|
|
78
91
|
}
|
|
79
92
|
throw new RetsyncWaitsForPromiseException(savedPromise);
|
|
80
93
|
}
|
|
81
|
-
const globalObj = {};
|
|
82
|
-
const resourcePromises = newDefaultWeakMap((key) => new Map());
|
|
83
94
|
/**
|
|
84
95
|
* Makes async code usable in retsync code.
|
|
85
96
|
* <p>
|
|
@@ -91,10 +102,15 @@ const resourcePromises = newDefaultWeakMap((key) => new Map());
|
|
|
91
102
|
* @param loaderFn
|
|
92
103
|
* @param idObj object to associate this call to. undefined means globally and the idKey primitive value is the only key.
|
|
93
104
|
* @param idKey Additional primitive key under idObj.
|
|
105
|
+
* @see cleanResource
|
|
94
106
|
*/
|
|
95
107
|
export function asyncResource2retsync(loaderFn, idObj, idKey) {
|
|
96
|
-
|
|
97
|
-
|
|
108
|
+
// Validity check:
|
|
109
|
+
if (!idObj && !idKey) {
|
|
110
|
+
throw new Error("Either idObj or idKey must be specified");
|
|
111
|
+
}
|
|
112
|
+
idObj = idObj || _global.globalObj;
|
|
113
|
+
const promisesForIdObj = _global.resourcePromises.get(idObj);
|
|
98
114
|
let promise = promisesForIdObj.get(idKey);
|
|
99
115
|
if (!promise) {
|
|
100
116
|
promise = loaderFn();
|
|
@@ -111,6 +127,21 @@ export function asyncResource2retsync(loaderFn, idObj, idKey) {
|
|
|
111
127
|
throw e;
|
|
112
128
|
}
|
|
113
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Cleans the promise and therefore the result behind the given obj+key like used in {@link asyncResource2retsync}.
|
|
132
|
+
* Call this i.e. on the event that the resource has change and you want to "invalidate the cached value", so it will be fetched fresh next time.
|
|
133
|
+
* @param idObj
|
|
134
|
+
* @param idKey
|
|
135
|
+
*/
|
|
136
|
+
function cleanResource(idObj, idKey) {
|
|
137
|
+
// Validity check:
|
|
138
|
+
if (!idObj && !idKey) {
|
|
139
|
+
throw new Error("Either idObj or idKey must be specified");
|
|
140
|
+
}
|
|
141
|
+
idObj = idObj || _global.globalObj;
|
|
142
|
+
const promisesForIdObj = _global.resourcePromises.get(idObj);
|
|
143
|
+
promisesForIdObj.delete(idKey);
|
|
144
|
+
}
|
|
114
145
|
export class RetsyncWaitsForPromiseException extends Error {
|
|
115
146
|
constructor(promise) {
|
|
116
147
|
super("Some retsync style code (see call stack / caller of promise2retsync) wants to await an async operation. To make this possible, you need to wrapt it at some ancestor caller level with retsync2promise. I.e. 'const result = await retsync2promise(() => {...your **retryable*** - synchronous code...}});");
|
|
@@ -118,7 +149,7 @@ export class RetsyncWaitsForPromiseException extends Error {
|
|
|
118
149
|
}
|
|
119
150
|
}
|
|
120
151
|
export function checkThatCallerHandlesRetsync() {
|
|
121
|
-
if (!
|
|
152
|
+
if (!_global.retsync2promiseCall) {
|
|
122
153
|
throw new Error("The method, you are calling uses retsync code and needs to be wrapped at some ancestor caller level with retsync2promise. I.e. 'const result = await retsync2promise(() => {...call the function that (deep inside) uses **retryable*** - synchronous code...}});");
|
|
123
154
|
}
|
|
124
155
|
}
|
package/dist/esm/retsync.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retsync.js","sourceRoot":"","sources":["../../retsync.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,0JAA0J;AAC1J,2CAA2C;AAC3C,2HAA2H;AAC3H,8SAA8S;AAG9S,OAAO,EAAC,iBAAiB,EAAC,MAAM,QAAQ,CAAC;AASzC,MAAM,
|
|
1
|
+
{"version":3,"file":"retsync.js","sourceRoot":"","sources":["../../retsync.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/retsync.ts
CHANGED
|
@@ -14,9 +14,23 @@ type Retsync2promiseOptions = {
|
|
|
14
14
|
checkSaved?: boolean
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Internal / used in frameworks.
|
|
19
|
+
*/
|
|
20
|
+
export class Retsync2promiseCall {
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Global state. Internal / shared with frameworks.
|
|
26
|
+
*/
|
|
27
|
+
export const _global = new class {
|
|
28
|
+
resolvedPromiseValues = new WeakMap<Promise<any>, unknown>();
|
|
29
|
+
retsync2promiseCall?: Retsync2promiseCall;
|
|
30
|
+
globalObj = {};
|
|
31
|
+
resourcePromises = newDefaultWeakMap((key) => new Map<string | number | undefined, Promise<unknown>>())
|
|
32
|
+
}
|
|
18
33
|
|
|
19
|
-
let callerHandlesRetsync = false
|
|
20
34
|
/**
|
|
21
35
|
* Let's you run retsync code and wait, till it is finished.
|
|
22
36
|
* @param repeatableFn
|
|
@@ -24,16 +38,16 @@ let callerHandlesRetsync = false
|
|
|
24
38
|
*/
|
|
25
39
|
export async function retsync2promise<T>(repeatableFn: () => T, options: Retsync2promiseOptions = {}): Promise<T> {
|
|
26
40
|
/**
|
|
27
|
-
* ...while
|
|
41
|
+
* ...while indicating that it is being called
|
|
28
42
|
*/
|
|
29
43
|
function runRepeatableFn() {
|
|
30
|
-
const
|
|
44
|
+
const orig_retsync2promiseCall = _global.retsync2promiseCall;
|
|
31
45
|
try {
|
|
32
|
-
|
|
46
|
+
_global.retsync2promiseCall = new Retsync2promiseCall();
|
|
33
47
|
return repeatableFn();
|
|
34
48
|
}
|
|
35
49
|
finally {
|
|
36
|
-
|
|
50
|
+
_global.retsync2promiseCall = orig_retsync2promiseCall;
|
|
37
51
|
}
|
|
38
52
|
}
|
|
39
53
|
|
|
@@ -41,7 +55,7 @@ export async function retsync2promise<T>(repeatableFn: () => T, options: Retsync
|
|
|
41
55
|
try {
|
|
42
56
|
return runRepeatableFn();
|
|
43
57
|
} catch (e) {
|
|
44
|
-
if (e instanceof RetsyncWaitsForPromiseException) {
|
|
58
|
+
if (e != null && e instanceof RetsyncWaitsForPromiseException) {
|
|
45
59
|
if (e.checkSaved || (e.checkSaved === undefined && options.checkSaved !== false)) {
|
|
46
60
|
const optionHint = `Hint: See also: Retsync2promiseOptions#checkSaved`
|
|
47
61
|
// Check if repeatableFn is behaving in repeatable symantics and saves the promise
|
|
@@ -65,7 +79,7 @@ export async function retsync2promise<T>(repeatableFn: () => T, options: Retsync
|
|
|
65
79
|
}
|
|
66
80
|
}
|
|
67
81
|
|
|
68
|
-
resolvedPromiseValues.set(e.promise, await e.promise);
|
|
82
|
+
_global.resolvedPromiseValues.set(e.promise, await e.promise);
|
|
69
83
|
// Try again. Now it will hit the resolved value
|
|
70
84
|
} else {
|
|
71
85
|
throw e;
|
|
@@ -87,16 +101,13 @@ export async function retsync2promise<T>(repeatableFn: () => T, options: Retsync
|
|
|
87
101
|
* @param savedPromise You must save/fix the promise somewhere, so you reuse it the next time you encounter it.
|
|
88
102
|
*/
|
|
89
103
|
export function promise2retsync<T>(savedPromise: Promise<T>): T {
|
|
90
|
-
if(resolvedPromiseValues.has(savedPromise)) {
|
|
91
|
-
return resolvedPromiseValues.get(savedPromise) as T;
|
|
104
|
+
if(_global.resolvedPromiseValues.has(savedPromise)) {
|
|
105
|
+
return _global.resolvedPromiseValues.get(savedPromise) as T;
|
|
92
106
|
}
|
|
93
107
|
|
|
94
108
|
throw new RetsyncWaitsForPromiseException(savedPromise)
|
|
95
109
|
}
|
|
96
110
|
|
|
97
|
-
const globalObj = {};
|
|
98
|
-
const resourcePromises = newDefaultWeakMap((key) => new Map<string | number | undefined, Promise<unknown>>())
|
|
99
|
-
|
|
100
111
|
/**
|
|
101
112
|
* Makes async code usable in retsync code.
|
|
102
113
|
* <p>
|
|
@@ -108,11 +119,17 @@ const resourcePromises = newDefaultWeakMap((key) => new Map<string | number | un
|
|
|
108
119
|
* @param loaderFn
|
|
109
120
|
* @param idObj object to associate this call to. undefined means globally and the idKey primitive value is the only key.
|
|
110
121
|
* @param idKey Additional primitive key under idObj.
|
|
122
|
+
* @see cleanResource
|
|
111
123
|
*/
|
|
112
124
|
export function asyncResource2retsync<T>(loaderFn: ()=> Promise<T>, idObj: object | undefined, idKey?: (string|number)): T {
|
|
113
|
-
|
|
125
|
+
// Validity check:
|
|
126
|
+
if(!idObj && !idKey) {
|
|
127
|
+
throw new Error("Either idObj or idKey must be specified");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
idObj = idObj || _global.globalObj;
|
|
114
131
|
|
|
115
|
-
const promisesForIdObj = resourcePromises.get(idObj);
|
|
132
|
+
const promisesForIdObj = _global.resourcePromises.get(idObj);
|
|
116
133
|
|
|
117
134
|
let promise = promisesForIdObj.get(idKey);
|
|
118
135
|
if(!promise) {
|
|
@@ -131,6 +148,23 @@ export function asyncResource2retsync<T>(loaderFn: ()=> Promise<T>, idObj: objec
|
|
|
131
148
|
}
|
|
132
149
|
}
|
|
133
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Cleans the promise and therefore the result behind the given obj+key like used in {@link asyncResource2retsync}.
|
|
153
|
+
* Call this i.e. on the event that the resource has change and you want to "invalidate the cached value", so it will be fetched fresh next time.
|
|
154
|
+
* @param idObj
|
|
155
|
+
* @param idKey
|
|
156
|
+
*/
|
|
157
|
+
function cleanResource(idObj: object | undefined, idKey?: (string|number)) {
|
|
158
|
+
// Validity check:
|
|
159
|
+
if(!idObj && !idKey) {
|
|
160
|
+
throw new Error("Either idObj or idKey must be specified");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
idObj = idObj || _global.globalObj;
|
|
164
|
+
const promisesForIdObj = _global.resourcePromises.get(idObj);
|
|
165
|
+
promisesForIdObj.delete(idKey);
|
|
166
|
+
}
|
|
167
|
+
|
|
134
168
|
|
|
135
169
|
|
|
136
170
|
export class RetsyncWaitsForPromiseException extends Error {
|
|
@@ -147,7 +181,7 @@ export class RetsyncWaitsForPromiseException extends Error {
|
|
|
147
181
|
}
|
|
148
182
|
|
|
149
183
|
export function checkThatCallerHandlesRetsync() {
|
|
150
|
-
if(!
|
|
184
|
+
if(!_global.retsync2promiseCall) {
|
|
151
185
|
throw new Error("The method, you are calling uses retsync code and needs to be wrapped at some ancestor caller level with retsync2promise. I.e. 'const result = await retsync2promise(() => {...call the function that (deep inside) uses **retryable*** - synchronous code...}});");
|
|
152
186
|
}
|
|
153
187
|
}
|