2
2
import { isPromise } from '../promise' ;
3
3
import { resolveProp } from './resolver' ;
4
4
5
+ /**
6
+ * A decorator that gates the execution of a method or getter.
7
+ * It ensures that the decorated method is executed only once at a time
8
+ * by forcing subsequent calls to wait for the previous execution to complete.
9
+ */
5
10
export function gate < T extends ( ...arg : any ) => any > ( resolver ?: ( ...args : Parameters < T > ) => string ) {
6
11
return ( target : any , key : string , descriptor : PropertyDescriptor ) => {
12
+ // Stores the original method or getter function in fn variable
7
13
let fn : Function | undefined ;
8
14
if ( typeof descriptor . value === 'function' ) {
9
15
fn = descriptor . value ;
@@ -12,10 +18,15 @@ export function gate<T extends (...arg: any) => any>(resolver?: (...args: Parame
12
18
}
13
19
if ( fn == null ) throw new Error ( 'Not supported' ) ;
14
20
21
+ // Creates a unique gate key
15
22
const gateKey = `$gate$${ key } ` ;
16
23
24
+ // Replaces the descriptor value with a new function
17
25
descriptor . value = function ( this : any , ...args : any [ ] ) {
26
+ // Resolves the gate key using the resolver function
18
27
const prop = resolveProp ( gateKey , resolver , ...( args as Parameters < T > ) ) ;
28
+
29
+ // Checks if a promise has already been created for the method
19
30
if ( ! Object . prototype . hasOwnProperty . call ( this , prop ) ) {
20
31
Object . defineProperty ( this , prop , {
21
32
configurable : false ,
@@ -25,15 +36,21 @@ export function gate<T extends (...arg: any) => any>(resolver?: (...args: Parame
25
36
} ) ;
26
37
}
27
38
39
+ // If a promise exists, return it
28
40
let promise = this [ prop ] ;
29
41
if ( promise === undefined ) {
30
42
let result ;
31
43
try {
44
+ // Call the original method
32
45
result = fn ! . apply ( this , args ) ;
46
+
47
+ // If the result is not a promise, return it
33
48
if ( result == null || ! isPromise ( result ) ) {
34
49
return result ;
35
50
}
36
51
52
+ // If the result is a promise, set up .then and .catch
53
+ // handlers to clear the promise on completion
37
54
this [ prop ] = promise = result
38
55
. then ( ( r : any ) => {
39
56
this [ prop ] = undefined ;
@@ -49,6 +66,7 @@ export function gate<T extends (...arg: any) => any>(resolver?: (...args: Parame
49
66
}
50
67
}
51
68
69
+ // Return the ongoing promise
52
70
return promise ;
53
71
} ;
54
72
} ;
0 commit comments