react-broadcast-sync 1.0.0 → 1.1.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/.eslintignore +5 -0
- package/.github/workflows/ci.yml +3 -3
- package/.github/workflows/release.yml +39 -0
- package/.husky/pre-commit +0 -1
- package/.nvmrc +1 -0
- package/.prettierignore +1 -0
- package/.prettierrc +5 -1
- package/CHANGELOG.md +20 -0
- package/README.md +118 -47
- package/demo/react-broadcast-sync-demo/README.md +130 -0
- package/demo/react-broadcast-sync-demo/index.html +14 -0
- package/demo/react-broadcast-sync-demo/package-lock.json +6379 -0
- package/demo/react-broadcast-sync-demo/package.json +42 -0
- package/demo/react-broadcast-sync-demo/public/assets/react-broadcast-sync-logo.png +0 -0
- package/demo/react-broadcast-sync-demo/src/App.tsx +277 -0
- package/demo/react-broadcast-sync-demo/src/components/Counter.tsx +63 -0
- package/demo/react-broadcast-sync-demo/src/components/TextSync.tsx +61 -0
- package/demo/react-broadcast-sync-demo/src/components/TodoList.tsx +186 -0
- package/demo/react-broadcast-sync-demo/src/hooks/useCounterBroadcast.ts +94 -0
- package/demo/react-broadcast-sync-demo/src/hooks/useTextBroadcast.ts +37 -0
- package/demo/react-broadcast-sync-demo/src/hooks/useTodoBroadcast.ts +249 -0
- package/demo/react-broadcast-sync-demo/src/main.tsx +11 -0
- package/demo/react-broadcast-sync-demo/src/theme.ts +62 -0
- package/demo/react-broadcast-sync-demo/tsconfig.json +26 -0
- package/demo/react-broadcast-sync-demo/tsconfig.node.json +10 -0
- package/demo/react-broadcast-sync-demo/vite.config.ts +12 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/eslint.config.js +14 -5
- package/jest.config.cjs +8 -9
- package/package.json +63 -33
- package/rollup.config.mjs +27 -21
- package/src/BroadcastProvider.tsx +6 -6
- package/src/hooks/useBroadcastChannel.ts +122 -95
- package/src/index.ts +1 -1
- package/src/tests/BroadcastProvider.test.tsx +7 -7
- package/src/tests/debug.test.ts +65 -25
- package/src/tests/messageUtils.test.ts +20 -15
- package/src/tests/useBroadcastChannel.test.tsx +48 -33
- package/src/types/types.ts +19 -23
- package/src/utils/debug.ts +1 -1
- package/src/utils/messageUtils.ts +19 -24
- package/dist/useBroadcastChannel.d.ts +0 -3
|
@@ -28,7 +28,7 @@ class MockBroadcastChannel {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const waitForChannel = async () => {
|
|
31
|
-
return new Promise<void>(
|
|
31
|
+
return new Promise<void>(resolve => {
|
|
32
32
|
const checkChannel = () => {
|
|
33
33
|
if (mockChannels.length > 0) {
|
|
34
34
|
resolve();
|
|
@@ -73,7 +73,7 @@ describe('useBroadcastChannel', () => {
|
|
|
73
73
|
type: 'greeting',
|
|
74
74
|
message: { text: 'hi' },
|
|
75
75
|
source: 'another-tab',
|
|
76
|
-
timestamp: Date.now()
|
|
76
|
+
timestamp: Date.now(),
|
|
77
77
|
};
|
|
78
78
|
|
|
79
79
|
act(() => {
|
|
@@ -108,7 +108,7 @@ describe('useBroadcastChannel', () => {
|
|
|
108
108
|
type: 'greeting',
|
|
109
109
|
message: 'hi',
|
|
110
110
|
source: 'external',
|
|
111
|
-
timestamp: Date.now()
|
|
111
|
+
timestamp: Date.now(),
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
act(() => {
|
|
@@ -135,14 +135,14 @@ describe('useBroadcastChannel', () => {
|
|
|
135
135
|
type: 'a',
|
|
136
136
|
message: 'a',
|
|
137
137
|
source: 'x',
|
|
138
|
-
timestamp: Date.now()
|
|
138
|
+
timestamp: Date.now(),
|
|
139
139
|
});
|
|
140
140
|
channel.simulateMessage({
|
|
141
141
|
id: '2',
|
|
142
142
|
type: 'b',
|
|
143
143
|
message: 'b',
|
|
144
144
|
source: 'x',
|
|
145
|
-
timestamp: Date.now()
|
|
145
|
+
timestamp: Date.now(),
|
|
146
146
|
});
|
|
147
147
|
});
|
|
148
148
|
|
|
@@ -158,7 +158,7 @@ describe('useBroadcastChannel', () => {
|
|
|
158
158
|
it('clears sent message', async () => {
|
|
159
159
|
const { result } = renderHook(() => useBroadcastChannel('test-channel'));
|
|
160
160
|
await waitForChannel();
|
|
161
|
-
|
|
161
|
+
|
|
162
162
|
act(() => {
|
|
163
163
|
result.current.postMessage('test-type', { key: 'value' });
|
|
164
164
|
});
|
|
@@ -177,7 +177,7 @@ describe('useBroadcastChannel', () => {
|
|
|
177
177
|
jest.useFakeTimers();
|
|
178
178
|
|
|
179
179
|
const original = global.BroadcastChannel;
|
|
180
|
-
// @ts-
|
|
180
|
+
// @ts-expect-error - Testing invalid input
|
|
181
181
|
delete global.BroadcastChannel;
|
|
182
182
|
|
|
183
183
|
const { result } = renderHook(() => useBroadcastChannel('test-channel'));
|
|
@@ -200,7 +200,9 @@ describe('useBroadcastChannel', () => {
|
|
|
200
200
|
|
|
201
201
|
const { result } = renderHook(() => useBroadcastChannel('unsupported-channel'));
|
|
202
202
|
|
|
203
|
-
expect(result.current.error).toBe(
|
|
203
|
+
expect(result.current.error).toBe(
|
|
204
|
+
'BroadcastChannel is not supported in this browser. Please check browser compatibility.'
|
|
205
|
+
);
|
|
204
206
|
global.BroadcastChannel = original;
|
|
205
207
|
});
|
|
206
208
|
|
|
@@ -227,7 +229,7 @@ describe('useBroadcastChannel', () => {
|
|
|
227
229
|
message: 'expired',
|
|
228
230
|
source: 'another-tab',
|
|
229
231
|
timestamp: Date.now() - 1000000,
|
|
230
|
-
expirationDate: Date.now() - 1000000
|
|
232
|
+
expirationDate: Date.now() - 1000000,
|
|
231
233
|
};
|
|
232
234
|
|
|
233
235
|
act(() => {
|
|
@@ -238,7 +240,9 @@ describe('useBroadcastChannel', () => {
|
|
|
238
240
|
});
|
|
239
241
|
|
|
240
242
|
it('handles duplicate messages within TTL', async () => {
|
|
241
|
-
const { result } = renderHook(() =>
|
|
243
|
+
const { result } = renderHook(() =>
|
|
244
|
+
useBroadcastChannel('test-channel', { deduplicationTTL: 5000 })
|
|
245
|
+
);
|
|
242
246
|
await waitForChannel();
|
|
243
247
|
const channel = mockChannels[0];
|
|
244
248
|
|
|
@@ -247,7 +251,7 @@ describe('useBroadcastChannel', () => {
|
|
|
247
251
|
type: 'test',
|
|
248
252
|
message: 'duplicate',
|
|
249
253
|
source: 'another-tab',
|
|
250
|
-
timestamp: Date.now()
|
|
254
|
+
timestamp: Date.now(),
|
|
251
255
|
};
|
|
252
256
|
|
|
253
257
|
act(() => {
|
|
@@ -269,7 +273,7 @@ describe('useBroadcastChannel', () => {
|
|
|
269
273
|
type: 'test',
|
|
270
274
|
message: 'will be cleared',
|
|
271
275
|
source: 'another-tab',
|
|
272
|
-
timestamp: Date.now()
|
|
276
|
+
timestamp: Date.now(),
|
|
273
277
|
});
|
|
274
278
|
});
|
|
275
279
|
|
|
@@ -278,9 +282,10 @@ describe('useBroadcastChannel', () => {
|
|
|
278
282
|
act(() => {
|
|
279
283
|
channel.simulateMessage({
|
|
280
284
|
id: 'to-clear',
|
|
281
|
-
type:
|
|
285
|
+
type:
|
|
286
|
+
'__INTERNAL__:CLEAR_MESSAGE:' + btoa('react-broadcast-sync:CLEAR_MESSAGE:test-channel-'),
|
|
282
287
|
source: 'another-tab',
|
|
283
|
-
timestamp: Date.now()
|
|
288
|
+
timestamp: Date.now(),
|
|
284
289
|
});
|
|
285
290
|
});
|
|
286
291
|
|
|
@@ -298,14 +303,14 @@ describe('useBroadcastChannel', () => {
|
|
|
298
303
|
type: 'test1',
|
|
299
304
|
message: 'first',
|
|
300
305
|
source: 'another-tab',
|
|
301
|
-
timestamp: Date.now()
|
|
306
|
+
timestamp: Date.now(),
|
|
302
307
|
});
|
|
303
308
|
channel.simulateMessage({
|
|
304
309
|
id: 'msg2',
|
|
305
310
|
type: 'test2',
|
|
306
311
|
message: 'second',
|
|
307
312
|
source: 'another-tab',
|
|
308
|
-
timestamp: Date.now()
|
|
313
|
+
timestamp: Date.now(),
|
|
309
314
|
});
|
|
310
315
|
});
|
|
311
316
|
|
|
@@ -313,10 +318,14 @@ describe('useBroadcastChannel', () => {
|
|
|
313
318
|
|
|
314
319
|
act(() => {
|
|
315
320
|
channel.simulateMessage({
|
|
316
|
-
id:
|
|
317
|
-
|
|
321
|
+
id:
|
|
322
|
+
'__INTERNAL__:CLEAR_ALL_MESSAGES:' +
|
|
323
|
+
btoa('react-broadcast-sync:CLEAR_ALL_MESSAGES:test-channel-'),
|
|
324
|
+
type:
|
|
325
|
+
'__INTERNAL__:CLEAR_ALL_MESSAGES:' +
|
|
326
|
+
btoa('react-broadcast-sync:CLEAR_ALL_MESSAGES:test-channel-'),
|
|
318
327
|
source: 'another-tab',
|
|
319
|
-
timestamp: Date.now()
|
|
328
|
+
timestamp: Date.now(),
|
|
320
329
|
});
|
|
321
330
|
});
|
|
322
331
|
|
|
@@ -325,7 +334,9 @@ describe('useBroadcastChannel', () => {
|
|
|
325
334
|
|
|
326
335
|
it('performs cleanup of expired messages', async () => {
|
|
327
336
|
jest.useFakeTimers();
|
|
328
|
-
const { result } = renderHook(() =>
|
|
337
|
+
const { result } = renderHook(() =>
|
|
338
|
+
useBroadcastChannel('test-channel', { cleaningInterval: 1000 })
|
|
339
|
+
);
|
|
329
340
|
await waitForChannel();
|
|
330
341
|
const channel = mockChannels[0];
|
|
331
342
|
|
|
@@ -336,7 +347,7 @@ describe('useBroadcastChannel', () => {
|
|
|
336
347
|
message: 'expired',
|
|
337
348
|
source: 'another-tab',
|
|
338
349
|
timestamp: Date.now() - 1000000,
|
|
339
|
-
expirationDate: Date.now() - 1000000
|
|
350
|
+
expirationDate: Date.now() - 1000000,
|
|
340
351
|
});
|
|
341
352
|
});
|
|
342
353
|
|
|
@@ -349,7 +360,7 @@ describe('useBroadcastChannel', () => {
|
|
|
349
360
|
});
|
|
350
361
|
|
|
351
362
|
it('handles registered types filtering', async () => {
|
|
352
|
-
const { result } = renderHook(() =>
|
|
363
|
+
const { result } = renderHook(() =>
|
|
353
364
|
useBroadcastChannel('test-channel', { registeredTypes: ['allowed-type'] })
|
|
354
365
|
);
|
|
355
366
|
await waitForChannel();
|
|
@@ -361,7 +372,7 @@ describe('useBroadcastChannel', () => {
|
|
|
361
372
|
type: 'unregistered-type',
|
|
362
373
|
message: 'test',
|
|
363
374
|
source: 'another-tab',
|
|
364
|
-
timestamp: Date.now()
|
|
375
|
+
timestamp: Date.now(),
|
|
365
376
|
});
|
|
366
377
|
});
|
|
367
378
|
|
|
@@ -373,7 +384,7 @@ describe('useBroadcastChannel', () => {
|
|
|
373
384
|
type: 'allowed-type',
|
|
374
385
|
message: 'test',
|
|
375
386
|
source: 'another-tab',
|
|
376
|
-
timestamp: Date.now()
|
|
387
|
+
timestamp: Date.now(),
|
|
377
388
|
});
|
|
378
389
|
});
|
|
379
390
|
|
|
@@ -381,7 +392,7 @@ describe('useBroadcastChannel', () => {
|
|
|
381
392
|
});
|
|
382
393
|
|
|
383
394
|
it('handles keepLatestMessage option', async () => {
|
|
384
|
-
const { result } = renderHook(() =>
|
|
395
|
+
const { result } = renderHook(() =>
|
|
385
396
|
useBroadcastChannel('test-channel', { keepLatestMessage: true })
|
|
386
397
|
);
|
|
387
398
|
await waitForChannel();
|
|
@@ -393,14 +404,14 @@ describe('useBroadcastChannel', () => {
|
|
|
393
404
|
type: 'test',
|
|
394
405
|
message: 'first',
|
|
395
406
|
source: 'another-tab',
|
|
396
|
-
timestamp: Date.now()
|
|
407
|
+
timestamp: Date.now(),
|
|
397
408
|
});
|
|
398
409
|
channel.simulateMessage({
|
|
399
410
|
id: 'msg2',
|
|
400
411
|
type: 'test',
|
|
401
412
|
message: 'second',
|
|
402
413
|
source: 'another-tab',
|
|
403
|
-
timestamp: Date.now()
|
|
414
|
+
timestamp: Date.now(),
|
|
404
415
|
});
|
|
405
416
|
});
|
|
406
417
|
|
|
@@ -410,10 +421,10 @@ describe('useBroadcastChannel', () => {
|
|
|
410
421
|
|
|
411
422
|
it('handles cleanup debounce', async () => {
|
|
412
423
|
jest.useFakeTimers();
|
|
413
|
-
const { result } = renderHook(() =>
|
|
414
|
-
useBroadcastChannel('test-channel', {
|
|
424
|
+
const { result } = renderHook(() =>
|
|
425
|
+
useBroadcastChannel('test-channel', {
|
|
415
426
|
cleaningInterval: 1000,
|
|
416
|
-
cleanupDebounceMs: 500
|
|
427
|
+
cleanupDebounceMs: 500,
|
|
417
428
|
})
|
|
418
429
|
);
|
|
419
430
|
await waitForChannel();
|
|
@@ -426,7 +437,7 @@ describe('useBroadcastChannel', () => {
|
|
|
426
437
|
message: 'expired',
|
|
427
438
|
source: 'another-tab',
|
|
428
439
|
timestamp: Date.now() - 1000000,
|
|
429
|
-
expirationDate: Date.now() - 1000000
|
|
440
|
+
expirationDate: Date.now() - 1000000,
|
|
430
441
|
});
|
|
431
442
|
});
|
|
432
443
|
|
|
@@ -463,7 +474,9 @@ describe('useBroadcastChannel', () => {
|
|
|
463
474
|
|
|
464
475
|
const badMessage: any = {};
|
|
465
476
|
Object.defineProperty(badMessage, 'id', {
|
|
466
|
-
get() {
|
|
477
|
+
get() {
|
|
478
|
+
throw new Error('fail');
|
|
479
|
+
},
|
|
467
480
|
});
|
|
468
481
|
badMessage.type = 'test';
|
|
469
482
|
badMessage.source = 'z';
|
|
@@ -484,7 +497,9 @@ describe('useBroadcastChannel', () => {
|
|
|
484
497
|
|
|
485
498
|
const { result } = renderHook(() => useBroadcastChannel('test-channel'));
|
|
486
499
|
|
|
487
|
-
expect(result.current.error).toBe(
|
|
500
|
+
expect(result.current.error).toBe(
|
|
501
|
+
'BroadcastChannel is not supported in this browser. Please check browser compatibility.'
|
|
502
|
+
);
|
|
488
503
|
|
|
489
504
|
global.BroadcastChannel = originalBroadcastChannel;
|
|
490
505
|
});
|
package/src/types/types.ts
CHANGED
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
export interface BroadcastOptions {
|
|
5
5
|
/** Custom source name for this instance */
|
|
6
6
|
sourceName?: string;
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
/** Interval in milliseconds for cleaning expired messages (default: 1000) */
|
|
9
9
|
cleaningInterval?: number;
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
/** If true, only the latest message is kept */
|
|
12
12
|
keepLatestMessage?: boolean;
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
/** Array of allowed message types */
|
|
15
15
|
registeredTypes?: string[];
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
/** Channel namespace for isolation */
|
|
18
18
|
namespace?: string;
|
|
19
19
|
|
|
@@ -30,7 +30,7 @@ export interface BroadcastOptions {
|
|
|
30
30
|
export interface SendMessageOptions {
|
|
31
31
|
/** Message expiration duration in milliseconds */
|
|
32
32
|
expirationDuration?: number;
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
/** Specific expiration timestamp */
|
|
35
35
|
expirationDate?: number;
|
|
36
36
|
}
|
|
@@ -41,19 +41,19 @@ export interface SendMessageOptions {
|
|
|
41
41
|
export interface BroadcastMessage {
|
|
42
42
|
/** Unique message identifier */
|
|
43
43
|
id: string;
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
/** Message type for categorization */
|
|
46
46
|
type: string;
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
/** Message content */
|
|
49
49
|
message: any;
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
/** Creation timestamp */
|
|
52
52
|
timestamp: number;
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
/** Source identifier */
|
|
55
55
|
source: string;
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
/** Optional expiration timestamp */
|
|
58
58
|
expirationDate?: number;
|
|
59
59
|
}
|
|
@@ -64,29 +64,25 @@ export interface BroadcastMessage {
|
|
|
64
64
|
export interface BroadcastActions {
|
|
65
65
|
/** The resolved channel name including namespace */
|
|
66
66
|
channelName: string;
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
/** Array of received messages */
|
|
69
69
|
messages: BroadcastMessage[];
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
/** Array of sent messages */
|
|
72
72
|
sentMessages: BroadcastMessage[];
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
/** Function to send a message */
|
|
75
|
-
postMessage: (
|
|
76
|
-
|
|
77
|
-
messageContent: any,
|
|
78
|
-
options?: SendMessageOptions
|
|
79
|
-
) => void;
|
|
80
|
-
|
|
75
|
+
postMessage: (messageType: string, messageContent: any, options?: SendMessageOptions) => void;
|
|
76
|
+
|
|
81
77
|
/** Function to clear a specific message */
|
|
82
78
|
clearMessage: (id: string) => void;
|
|
83
|
-
|
|
79
|
+
|
|
84
80
|
/** Function to clear all messages */
|
|
85
81
|
clearAllMessages: () => void;
|
|
86
|
-
|
|
82
|
+
|
|
87
83
|
/** Function to clear a specific sent message */
|
|
88
84
|
clearSentMessage: (id: string) => void;
|
|
89
|
-
|
|
85
|
+
|
|
90
86
|
/** Current error state */
|
|
91
87
|
error: string | null;
|
|
92
|
-
}
|
|
88
|
+
}
|
package/src/utils/debug.ts
CHANGED
|
@@ -37,28 +37,30 @@ export const createMessage = (
|
|
|
37
37
|
message: content,
|
|
38
38
|
timestamp,
|
|
39
39
|
source,
|
|
40
|
-
expirationDate:
|
|
40
|
+
expirationDate:
|
|
41
|
+
options.expirationDate ??
|
|
41
42
|
(options.expirationDuration ? timestamp + options.expirationDuration : undefined),
|
|
42
43
|
};
|
|
43
44
|
};
|
|
44
45
|
|
|
45
|
-
|
|
46
46
|
export const getInternalMessageType = (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
47
|
+
baseType: 'CLEAR_MESSAGE' | 'CLEAR_ALL_MESSAGES',
|
|
48
|
+
channelName: string,
|
|
49
|
+
namespace = ''
|
|
50
|
+
): string => {
|
|
51
|
+
const fullChannel = `${channelName}-${namespace}`;
|
|
52
|
+
const input = `${SECRET}:${baseType}:${fullChannel}`;
|
|
53
|
+
const hash = btoa(input); // optional: use sha256 if added
|
|
54
|
+
return `${INTERNAL_PREFIX}:${baseType}:${hash}`;
|
|
55
|
+
};
|
|
56
56
|
|
|
57
57
|
export const isInternalType = (type: string): boolean => {
|
|
58
|
-
|
|
58
|
+
return type.startsWith(`${INTERNAL_PREFIX}:`);
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
export const isValidInternalClearMessage = (
|
|
61
|
+
export const isValidInternalClearMessage = (
|
|
62
|
+
message: any
|
|
63
|
+
): message is { id: string; type: string; source: string } => {
|
|
62
64
|
return (
|
|
63
65
|
message &&
|
|
64
66
|
typeof message === 'object' &&
|
|
@@ -67,7 +69,7 @@ export const isValidInternalClearMessage = (message: any): message is { id: stri
|
|
|
67
69
|
typeof message.type === 'string' &&
|
|
68
70
|
isInternalType(message.type)
|
|
69
71
|
);
|
|
70
|
-
}
|
|
72
|
+
};
|
|
71
73
|
|
|
72
74
|
export const debounce = <T extends (...args: any[]) => any>(
|
|
73
75
|
fn: T,
|
|
@@ -78,23 +80,18 @@ export const debounce = <T extends (...args: any[]) => any>(
|
|
|
78
80
|
} => {
|
|
79
81
|
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
80
82
|
let lastArgs: Parameters<T> | null = null;
|
|
81
|
-
let lastThis: any = null;
|
|
82
83
|
let result: ReturnType<T> | undefined;
|
|
83
84
|
|
|
84
|
-
const debounced =
|
|
85
|
+
const debounced = (...args: Parameters<T>) => {
|
|
85
86
|
lastArgs = args;
|
|
86
|
-
lastThis = this;
|
|
87
|
-
|
|
88
87
|
if (timeoutId !== null) {
|
|
89
88
|
clearTimeout(timeoutId);
|
|
90
89
|
}
|
|
91
|
-
|
|
92
90
|
timeoutId = setTimeout(() => {
|
|
93
91
|
timeoutId = null;
|
|
94
92
|
if (lastArgs !== null) {
|
|
95
|
-
result = fn
|
|
93
|
+
result = fn(...lastArgs);
|
|
96
94
|
lastArgs = null;
|
|
97
|
-
lastThis = null;
|
|
98
95
|
}
|
|
99
96
|
}, wait);
|
|
100
97
|
};
|
|
@@ -104,7 +101,6 @@ export const debounce = <T extends (...args: any[]) => any>(
|
|
|
104
101
|
clearTimeout(timeoutId);
|
|
105
102
|
timeoutId = null;
|
|
106
103
|
lastArgs = null;
|
|
107
|
-
lastThis = null;
|
|
108
104
|
}
|
|
109
105
|
};
|
|
110
106
|
|
|
@@ -113,9 +109,8 @@ export const debounce = <T extends (...args: any[]) => any>(
|
|
|
113
109
|
clearTimeout(timeoutId);
|
|
114
110
|
timeoutId = null;
|
|
115
111
|
if (lastArgs !== null) {
|
|
116
|
-
result = fn
|
|
112
|
+
result = fn(...lastArgs);
|
|
117
113
|
lastArgs = null;
|
|
118
|
-
lastThis = null;
|
|
119
114
|
}
|
|
120
115
|
}
|
|
121
116
|
return result;
|