@dxos/async 0.8.3 → 0.8.4-main.84f28bd

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/async",
3
- "version": "0.8.3",
3
+ "version": "0.8.4-main.84f28bd",
4
4
  "description": "Async utilities.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -29,12 +29,12 @@
29
29
  "dependencies": {
30
30
  "zen-observable": "^0.10.0",
31
31
  "zen-push": "^0.3.1",
32
- "@dxos/debug": "0.8.3",
33
- "@dxos/context": "0.8.3",
34
- "@dxos/invariant": "0.8.3",
35
- "@dxos/log": "0.8.3",
36
- "@dxos/util": "0.8.3",
37
- "@dxos/node-std": "0.8.3"
32
+ "@dxos/context": "0.8.4-main.84f28bd",
33
+ "@dxos/debug": "0.8.4-main.84f28bd",
34
+ "@dxos/invariant": "0.8.4-main.84f28bd",
35
+ "@dxos/log": "0.8.4-main.84f28bd",
36
+ "@dxos/node-std": "0.8.4-main.84f28bd",
37
+ "@dxos/util": "0.8.4-main.84f28bd"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/zen-observable": "^0.8.3"
@@ -0,0 +1,58 @@
1
+ //
2
+ // Copyright 2020 DXOS.org
3
+ //
4
+
5
+ import { describe, expect, test } from 'vitest';
6
+
7
+ import { debounce } from './debounce';
8
+ import { sleep } from './timeout';
9
+
10
+ describe('debounce', () => {
11
+ test('debounces function calls', async () => {
12
+ let count = 0;
13
+ const fn = debounce(() => count++, 100);
14
+
15
+ // First call should not execute immediately
16
+ fn();
17
+ expect(count).toBe(0);
18
+
19
+ // Second call should reset the timer
20
+ fn();
21
+ expect(count).toBe(0);
22
+
23
+ // Wait for debounce window to pass
24
+ await sleep(150);
25
+ expect(count).toBe(1); // Only the last call should execute
26
+ });
27
+
28
+ test('passes arguments to debounced function', async () => {
29
+ let lastArgs: any[] = [];
30
+ const fn = debounce((...args: any[]) => {
31
+ lastArgs = args;
32
+ }, 100);
33
+
34
+ fn('test', 123);
35
+ expect(lastArgs).toEqual([]); // Should not execute immediately
36
+
37
+ // Call with different args
38
+ fn('different', 456);
39
+ expect(lastArgs).toEqual([]); // Should not execute immediately
40
+
41
+ await sleep(150);
42
+ expect(lastArgs).toEqual(['different', 456]); // Should execute with last args
43
+ });
44
+
45
+ test('handles multiple rapid calls', async () => {
46
+ let count = 0;
47
+ const fn = debounce(() => count++, 100);
48
+
49
+ // Make multiple rapid calls
50
+ for (let i = 0; i < 5; i++) {
51
+ fn();
52
+ }
53
+ expect(count).toBe(0); // Should not execute immediately
54
+
55
+ await sleep(150);
56
+ expect(count).toBe(1); // Should execute only once after wait
57
+ });
58
+ });
package/src/debounce.ts CHANGED
@@ -2,6 +2,8 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { throttle } from './throttle';
6
+
5
7
  /**
6
8
  * Debounce callback.
7
9
  */
@@ -12,3 +14,16 @@ export const debounce = (cb: (...args: any[]) => void, wait = 100): ((...args: a
12
14
  t = setTimeout(() => cb(...args), wait);
13
15
  };
14
16
  };
17
+
18
+ /**
19
+ * Debounce and throttle callback.
20
+ */
21
+ export const debounceAndThrottle = (cb: (...args: any[]) => void, wait = 100): ((...args: any[]) => void) => {
22
+ const debounced = debounce(cb, wait);
23
+ const throttled = throttle(cb, wait);
24
+
25
+ return (...args: any[]) => {
26
+ debounced(...args);
27
+ throttled(...args);
28
+ };
29
+ };
@@ -22,7 +22,7 @@ describe('Event', () => {
22
22
  pureCount++;
23
23
  });
24
24
 
25
- const debounced = event.debounce(80);
25
+ const debounced = event.debounce(200);
26
26
  debounced.on(() => {
27
27
  debounceCount++;
28
28
  });
package/src/index.ts CHANGED
@@ -20,6 +20,7 @@ export * from './stream-to-array';
20
20
  export * from './task-scheduling';
21
21
  export * from './test-stream';
22
22
  export * from './testing';
23
+ export * from './throttle';
23
24
  export * from './timeout';
24
25
  export * from './timer';
25
26
  export * from './track-leaks';
@@ -0,0 +1,65 @@
1
+ //
2
+ // Copyright 2020 DXOS.org
3
+ //
4
+
5
+ import { describe, expect, test } from 'vitest';
6
+
7
+ import { throttle } from './throttle';
8
+ import { sleep } from './timeout';
9
+
10
+ describe('throttle', () => {
11
+ test('throttles function calls', async () => {
12
+ let count = 0;
13
+ const fn = throttle(() => count++, 100);
14
+
15
+ // First call should execute immediately
16
+ fn();
17
+ expect(count).toBe(1);
18
+
19
+ // Second call within throttle window should not execute
20
+ fn();
21
+ expect(count).toBe(1);
22
+
23
+ // Wait for throttle window to pass
24
+ await sleep(150);
25
+
26
+ // Next call should execute
27
+ fn();
28
+ expect(count).toBe(2);
29
+ });
30
+
31
+ test('passes arguments to throttled function', async () => {
32
+ let lastArgs: any[] = [];
33
+ const fn = throttle((...args: any[]) => {
34
+ lastArgs = args;
35
+ }, 100);
36
+
37
+ fn('test', 123);
38
+ expect(lastArgs).toEqual(['test', 123]);
39
+
40
+ // Call with different args within throttle window
41
+ fn('different', 456);
42
+ expect(lastArgs).toEqual(['test', 123]); // Should not update
43
+
44
+ await sleep(150);
45
+ fn('new', 789);
46
+ expect(lastArgs).toEqual(['new', 789]);
47
+ });
48
+
49
+ test('handles multiple rapid calls', async () => {
50
+ let count = 0;
51
+ const fn = throttle(() => count++, 100);
52
+
53
+ // Make multiple rapid calls
54
+ for (let i = 0; i < 5; i++) {
55
+ fn();
56
+ }
57
+ expect(count).toBe(1); // Only first call should execute
58
+
59
+ await sleep(150);
60
+ expect(count).toBe(1); // Still only one execution
61
+
62
+ fn();
63
+ expect(count).toBe(2); // Next call after wait should execute
64
+ });
65
+ });
@@ -0,0 +1,14 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export const throttle = (cb: (...args: any[]) => void, wait = 100): ((...args: any[]) => void) => {
6
+ let lastCall = 0;
7
+ return (...args: any[]) => {
8
+ const now = Date.now();
9
+ if (now - lastCall >= wait) {
10
+ cb(...args);
11
+ lastCall = now;
12
+ }
13
+ };
14
+ };