@@ -11,46 +11,33 @@ export function asyncThrottle<TArgs extends ReadonlyArray<unknown>>(
11
11
) {
12
12
if ( typeof func !== 'function' ) throw new Error ( 'argument is not function.' )
13
13
14
- let running = false
15
- let lastTime = 0
16
- let timeout : ReturnType < typeof setTimeout >
17
- let currentArgs : TArgs | null = null
14
+ let nextExecutionTime = 0
15
+ let lastArgs = null
16
+ let isExecuting = false
17
+ let isScheduled = false
18
18
19
- const execFunc = async ( ) => {
20
- if ( currentArgs ) {
21
- const args = currentArgs
22
- currentArgs = null
19
+ return async ( ...args : TArgs ) => {
20
+ lastArgs = args
21
+ if ( isScheduled ) return
22
+ isScheduled = true
23
+ while ( isExecuting ) {
24
+ await new Promise ( ( done ) => setTimeout ( done , interval ) )
25
+ }
26
+ while ( Date . now ( ) < nextExecutionTime ) {
27
+ await new Promise ( ( done ) =>
28
+ setTimeout ( done , nextExecutionTime - Date . now ( ) ) ,
29
+ )
30
+ }
31
+ isScheduled = false
32
+ isExecuting = true
33
+ try {
34
+ await func ( ...lastArgs )
35
+ } catch ( error ) {
23
36
try {
24
- running = true
25
- await func ( ...args )
26
- } catch ( error ) {
27
37
onError ( error )
28
- } finally {
29
- lastTime = Date . now ( ) // this line must after 'func' executed to avoid two 'func' running in concurrent.
30
- running = false
31
- }
32
- }
33
- }
34
-
35
- const delayFunc = async ( ) => {
36
- clearTimeout ( timeout )
37
- timeout = setTimeout ( ( ) => {
38
- if ( running ) {
39
- delayFunc ( ) // Will come here when 'func' execution time is greater than the interval.
40
- } else {
41
- execFunc ( )
42
- }
43
- } , interval )
44
- }
45
-
46
- return ( ...args : TArgs ) => {
47
- currentArgs = args
48
-
49
- const tooSoon = Date . now ( ) - lastTime < interval
50
- if ( running || tooSoon ) {
51
- delayFunc ( )
52
- } else {
53
- execFunc ( )
38
+ } catch { }
54
39
}
40
+ nextExecutionTime = Date . now ( ) + interval
41
+ isExecuting = false
55
42
}
56
43
}
0 commit comments